Spaces:
Running
on
Zero
Running
on
Zero
| """ | |
| Copyright (c) 2024 The D-FINE Authors. All Rights Reserved. | |
| """ | |
| import os | |
| import json | |
| from PIL import Image | |
| from concurrent.futures import ThreadPoolExecutor | |
| import argparse | |
| def resize_image_and_update_annotations(image_path, annotations, max_size=640): | |
| print(f"Processing image: {image_path}") | |
| try: | |
| with Image.open(image_path) as img: | |
| w, h = img.size | |
| if max(w, h) <= max_size: | |
| return annotations, w, h, False # No need to resize | |
| scale = max_size / max(w, h) | |
| new_w = int(w * scale) | |
| new_h = int(h * scale) | |
| print(f"Resizing image to width={new_w}, height={new_h}") | |
| img = img.resize((new_w, new_h), Image.Resampling.LANCZOS) | |
| new_image_path = image_path.replace('.jpg', '_resized{}.jpg'.format(max_size)) | |
| img.save(new_image_path) | |
| print(f"Resized image saved: {new_image_path}") | |
| print(f"Original size: ({w}, {h}), New size: ({new_w}, {new_h})") | |
| # Update annotations | |
| for ann in annotations: | |
| ann['area'] = ann['area'] * (scale ** 2) | |
| ann['bbox'] = [coord * scale for coord in ann['bbox']] | |
| if 'orig_size' in ann: | |
| ann['orig_size'] = (new_w, new_h) | |
| if 'size' in ann: | |
| ann['size'] = (new_w, new_h) | |
| except Exception as e: | |
| print(f"Error processing {image_path}: {e}") | |
| return None | |
| return annotations, new_w, new_h, True | |
| def resize_images_and_update_annotations(base_dir, subset, max_size=640, num_workers=4): | |
| print(f"Starting to resize images and update annotations for subset: {subset}") | |
| json_file = os.path.join(base_dir, subset, 'new_zhiyuan_objv2_{}.json'.format(subset)) | |
| if not os.path.isfile(json_file): | |
| print(f'Error: JSON file not found at {json_file}') | |
| return | |
| print(f"Loading JSON file: {json_file}") | |
| with open(json_file, 'r') as f: | |
| data = json.load(f) | |
| print("JSON file loaded.") | |
| print("Preparing image annotations mapping...") | |
| image_annotations = {img['id']: [] for img in data['images']} | |
| for ann in data['annotations']: | |
| image_annotations[ann['image_id']].append(ann) | |
| print("Image annotations mapping prepared.") | |
| def process_image(image_info): | |
| image_path = os.path.join(base_dir, subset, image_info['file_name']) | |
| results = resize_image_and_update_annotations(image_path, image_annotations[image_info['id']], max_size) | |
| if results is None: | |
| updated_annotations, new_w, new_h, resized = None, None, None, None | |
| else: | |
| updated_annotations, new_w, new_h, resized = results | |
| return image_info, updated_annotations, new_w, new_h, resized | |
| print(f"Processing images with {num_workers} worker threads...") | |
| with ThreadPoolExecutor(max_workers=num_workers) as executor: | |
| results = list(executor.map(process_image, data['images'])) | |
| print("Image processing completed.") | |
| new_images = [] | |
| new_annotations = [] | |
| print("Updating image and annotation data...") | |
| for image_info, updated_annotations, new_w, new_h, resized in results: | |
| if updated_annotations is not None: | |
| image_info['width'] = new_w | |
| image_info['height'] = new_h | |
| image_annotations[image_info['id']] = updated_annotations | |
| if resized: | |
| image_info['file_name'] = image_info['file_name'].replace('.jpg', '_resized{}.jpg'.format(max_size)) | |
| new_images.append(image_info) | |
| new_annotations.extend(updated_annotations) | |
| print(f"Total images processed: {len(new_images)}") | |
| print(f"Total annotations updated: {len(new_annotations)}") | |
| new_data = { | |
| 'images': new_images, | |
| 'annotations': new_annotations, | |
| 'categories': data['categories'] | |
| } | |
| new_json_file = json_file.replace('.json', '_resized{}.json'.format(max_size)) | |
| print('Saving new training annotations...') | |
| with open(new_json_file, 'w') as f: | |
| json.dump(new_data, f) | |
| print(f'New JSON file saved to {new_json_file}') | |
| def parse_arguments(): | |
| parser = argparse.ArgumentParser(description='Resize images and update dataset annotations for both train and val sets.') | |
| parser.add_argument( | |
| '--base_dir', | |
| type=str, | |
| default='/datassd/objects365', | |
| help='Base directory of the dataset, e.g., /data/Objects365/data' | |
| ) | |
| parser.add_argument( | |
| '--max_size', | |
| type=int, | |
| default=640, | |
| help='Maximum size for the longer side of the image (default: 640)' | |
| ) | |
| parser.add_argument( | |
| '--num_workers', | |
| type=int, | |
| default=4, | |
| help='Number of worker threads for parallel processing (default: 4)' | |
| ) | |
| args = parser.parse_args() | |
| return args | |
| def main(): | |
| args = parse_arguments() | |
| base_dir = args.base_dir | |
| max_size = args.max_size | |
| num_workers = args.num_workers | |
| subsets = ['train', 'val'] | |
| for subset in subsets: | |
| print(f'Processing subset: {subset}') | |
| resize_images_and_update_annotations( | |
| base_dir=base_dir, | |
| subset=subset, | |
| max_size=max_size, | |
| num_workers=num_workers | |
| ) | |
| print("All subsets processed.") | |
| if __name__ == "__main__": | |
| main() | |