fastdup icon indicating copy to clipboard operation
fastdup copied to clipboard

[Feature request] Support for YOLO format bounding boxes

Open amirmk89 opened this issue 2 years ago • 3 comments

Add support for YOLO format bounding box annotations. We share this snippet to unblock current users and will include a thoroughly tested version in an upcoming release.

YOLO annotation format

The YOLO annotation contains directories with both image and annotation files, with corresponding names and different suffixes (e.g., 100.jpg and 100.txt). Each txt file contains one line for each object, formatted as: [class, x_center, y_center, width, height] with coordinates given in the range of [0,1] relative to image dimensions.

E.g.:

2 0.7378676470588236 0.5125 0.030147058823529412 0.055
2 0.3044117647058823 0.65375 0.041176470588235294 0.0725
3 0.736764705882353 0.453125 0.04264705882352941 0.06875

Classes are given using integers of class strings.

Snippet for parsing a YOLO format data directory:

import os
import fastdup
import pandas as pd
from PIL import Image

def parse_object(obj_str, img_w, img_h):
    item_list = obj_str.split(' ')
    class_id = item_list[0]
    cx_rel, cy_rel, w_rel, h_rel = [float(o) for o in item_list[1:]]
    
    x = round(img_w * (cx_rel - w_rel / 2))
    y = round(img_h * (cy_rel - h_rel / 2))
    w = round(img_w * w_rel)
    h = round(img_h * h_rel)
    return [class_id, x,y,w,h]

data_dir = '/path/to/your/yolo/data/'

img_file_list = [f for f in os.listdir(data_dir) if f.endswith('.jpg')]
annotation_list = []

for img_fn in img_file_list:
    img_full_path = os.path.join(data_dir, img_fn) 
    img_w, img_h = Image.open(img_full_path).size

    anot_full_path = img_full_path.replace('jpg', 'txt')
    with open(anot_full_path, 'r') as f:
        for o in f.readlines():
            bbox_field_list = parse_object(o, img_w, img_h)
            annotation_list.append([img_fn, img_w, img_h] + bbox_field_list)

columns=['img_filename', 'img_w', 'img_h', 'label',
                 'bbox_x', 'bbox_y', 'bbox_w', 'bbox_h']            
annotation_df = pd.DataFrame(annotation_list, columns=columns)

fd = fastdup.create(work_dir, input_dir=data_dir)
fd.run(annotations=annotation_df)

This is still under development. Please let us know if there are any further requests or issues.

Thanks

amirmk89 avatar Mar 02 '23 19:03 amirmk89

Hi @amirmk89 I'd suggest for option to supply label folder path separately since if the dataset is already split (as available in some public datasets, or has been used for training once), the label folder is usually separate.

Also, can we please use pybboxes for getting the VOC annotation from yolo boxes?

atmadeep avatar Mar 20 '24 09:03 atmadeep

Hi @amirmk89 we would love to work with you to make you successful. Can you please share an example input format you would like to support?

dbickson avatar Mar 20 '24 09:03 dbickson

columns=['img_filename', 'img_w', 'img_h', 'label', 'bbox_x', 'bbox_y', 'bbox_w', 'bbox_h']

Should be

columns=['filename', 'img_w', 'img_h', 'label', 'bbox_x', 'bbox_y', 'bbox_w', 'bbox_h']

Also fd.run(annotations=annotation_df) fails with

AssertionError: df_annot must contain unique filenames, found repeating filenames

When there is more than one label per image

mhornsby avatar Jun 19 '24 03:06 mhornsby