gpu_symbol / tools /dataset /resize_obj365.py
himipo's picture
first
63e9186
"""
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()