I have an image I want to augment. Its resolution is 8192x4230. I've labeled it with this tool and exported the annotations in COCO format. Now I need to pass this image and annotations to AugLy functions, but when I do so, it throws me this error Traceback (most recent call last): File "C:\Users\Admin\source\repos\augpy\aug.py", line 114, in apply_random_augmentation(input_path, output_path, count+1) File "C:\Users\Admin\source\repos\augpy\aug.py", line 72, in apply_random_augmentation img = aug_func(img, bboxes, metadata) File "C:\Users\Admin\source\repos\augpy\aug.py", line 16, in lambda x, bboxes, meta: imaugs.random_noise(x, bboxes=bboxes, bbox_format='coco', metadata=meta), File "D:\Python39\lib\site-packages\augly\image\functional.py", line 1981, in random_noise imutils.get_metadata( File "D:\Python39\lib\site-packages\augly\image\utils\metadata.py", line 190, in get_metadata transform_bboxes( File "D:\Python39\lib\site-packages\augly\image\utils\metadata.py", line 128, in transform_bboxes norm_bboxes = validate_and_normalize_bboxes(dst_bboxes, bbox_format, src_w, src_h) File "D:\Python39\lib\site-packages\augly\image\utils\metadata.py", line 46, in validate_and_normalize_bboxes assert ( AssertionError: Bounding box [569.0, 2868.0, 207.0, 264.0] is invalid or is not in coco format at an arbitrary point in time (that is, it could be thrown at both the 1st iteration of the augmenting loop, or at the 20th iteration). How do I fix this error? Thanks in advance. Code: import os, random, copy, json from PIL import Image import augly.image.functional as imaugs from pycocotools.coco import COCO # List of augmentations augmentations = [ lambda x, bboxes, meta: imaugs.blur(x, bboxes=bboxes, bbox_format='coco', metadata=meta, radius=random.uniform(0.5, 2.0)), lambda x, bboxes, meta: imaugs.brightness(x, bboxes=bboxes, bbox_format='coco', metadata=meta, factor=random.uniform(0.7, 1.3)), lambda x, bboxes, meta: imaugs.contrast(x, bboxes=bboxes, bbox_format='coco', metadata=meta, factor=random.uniform(0.7, 1.5)), lambda x, bboxes, meta: imaugs.hflip(x, bboxes=bboxes, bbox_format='coco', metadata=meta), lambda x, bboxes, meta: imaugs.vflip(x, bboxes=bboxes, bbox_format='coco', metadata=meta), lambda x, bboxes, meta: imaugs.rotate(x, bboxes=bboxes, bbox_format='coco', metadata=meta, degrees=random.randint(-30, 30)), lambda x, bboxes, meta: imaugs.saturation(x, bboxes=bboxes, bbox_format='coco', metadata=meta, factor=random.uniform(0.5, 1.5)), lambda x, bboxes, meta: imaugs.scale(x, bboxes=bboxes, bbox_format='coco', metadata=meta, factor=random.uniform(0.7, 1.3)), lambda x, bboxes, meta: imaugs.random_noise(x, bboxes=bboxes, bbox_format='coco', metadata=meta), lambda x, bboxes, meta: imaugs.overlay_emoji(x, bboxes=bboxes, bbox_format='coco', metadata=meta, emoji_size=0.1), lambda x, bboxes, meta: imaugs.overlay_text(x, bboxes=bboxes, bbox_format='coco', metadata=meta, opacity=0.5), ] # Annotation ID ann_id = 0 # Calculate segmentation from bbox def bbox_to_segmentation(bbox): x, y, w, h = bbox segmentation = [ [x, y, x + w, y, x + w, y + h, x, y + h] ] return segmentation input_dir = "input_images" output_dir = "augmented_images" os.makedirs(output_dir, exist_ok=True) annotation_file = input_dir + '/my_coco.json' coco = COCO(annotation_file) annotation_file_output = output_dir + '/my_coco.json' coco_output = copy.deepcopy(coco.dataset) annotation_template = copy.deepcopy(coco_output['annotations'][0]) img_template = copy.deepcopy(coco_output['images'][0]) coco_output['annotations'] = [] coco_output['images'] = [] image_id = 1 # Only one image annotation_ids = coco.getAnnIds(imgIds=image_id) annotations = coco.loadAnns(annotation_ids) original_bboxes = [ann['bbox'] for ann in annotations] input_images = [f for f in os.listdir(input_dir) if f.endswith(('.jpg', '.jpeg', '.png'))] if not input_images: raise FileNotFoundError("No images in input_images!") def apply_random_augmentation(image_path, output_path, img_num): global ann_id img = Image.open(image_path) num_augs = random.randint(1, 3) bboxes = [[float(num) for num in bbox] for bbox in copy.deepcopy(original_bboxes)] # Apply from 1 to 3 augs for _ in range(num_augs): aug_func = random.choice(augmentations) metadata = [] img = aug_func(img, bboxes, metadata) new_bboxes = [[int(x) for x in bbox] for bbox in metadata[0]['dst_bboxes']] print(f'{img_num} {str(new_bboxes) == str(bboxes)}') # Fill in resulting annotation for bbox in new_bboxes: new_annotation = copy.deepcopy(annotation_template) new_annotation['area'] = bbox[2] * bbox[3] new_annotation['segmentation'] = bbox_to_segmentation(bbox) new_annotation['iscrowd'] = 0 new_annotation['bbox'] = bbox new_annotation['id'] = ann_id + 1 new_annotation['image_id'] = img_num new_annotation['category_id'] = coco.anns[(ann_id % len(coco.anns)) + 1]['category_id'] coco_output['annotations'].append(new_annotation) ann_id+=1 # Fill in resulting image metainfo new_img = copy.deepcopy(img_template) new_img['id'] = img_num new_img['file_name'] = output_path new_img['height'] = img.height new_img['width'] = img.width coco_output['images'].append(new_img) img.save(output_path) total_augmentations = 100 aug_per_image = total_augmentations count = 0 for img_name in input_images: if count >= total_augmentations: break for i in range(aug_per_image): if count >= total_augmentations: break input_path = os.path.join(input_dir, img_name) output_path = os.path.join(output_dir, f"aug_{count+1}_{img_name}") apply_random_augmentation(input_path, output_path, count+1) count += 1 with open(annotation_file_output, "w") as f: json.dump(coco_output, f, indent=4) print("Done") Note: this code works well if None passed as metadata to augmentation functions. I also deliberately transform bbox values from ints to floats just in case. My setup is Python3.9 with augly version 1.0.0 at WSL-Ubuntu on Windows 10 host. P.S. There's apparently no "augly" tag on SO yet. Edit: the culprits were scale and rotate augmentations, which resized the image before processing bboxes, rendering them invalid. Now the question is, how to make them work properly? Continue reading...