[Python] AugLy fails to augment a COCO annotated dataset

Discussão em 'Python' iniciado por Stack, Junho 30, 2025.

  1. Stack

    Stack Membro Participativo

    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...

Compartilhe esta Página