ultralytics/JSON2YOLO

Solutions to 'make_dirs' problem in `labelbox_json2yolo.py` code

Leprechault opened this issue · 3 comments

I'd like to convert my label file in *json to YOLO * txt with to class ('bsb','wsb') using the labelbox_json2yolo.py.

In my data (image and label file) I have:

file = "https://raw.githubusercontent.com/Leprechault/trash/main/YT_EMBRAPA_002.zip" # Patch to zip file in GitHub

import json
import os
from pathlib import Path

import requests
import yaml
from PIL import Image
from tqdm import tqdm

from utils import make_dirs


def convert(file, zip=True):
    # Convert Labelbox JSON labels to YOLO labels
    names = ['bsb','wsb']  # class names
    file = Path(file)
    save_dir = make_dirs(file.stem)
    with open(file) as f:
        data = json.load(f)  # load JSON

    for img in tqdm(data, desc=f'Converting {file}'):
        im_path = img['Labeled Data']
        im = Image.open(requests.get(im_path, stream=True).raw if im_path.startswith('http') else im_path)  # open
        width, height = im.size  # image size
        label_path = save_dir / 'labels' / Path(img['External ID']).with_suffix('.txt').name
        image_path = save_dir / 'images' / img['External ID']
        im.save(image_path, quality=95, subsampling=0)

        for label in img['Label']['objects']:
            # box
            top, left, h, w = label['bbox'].values()  # top, left, height, width
            xywh = [(left + w / 2) / width, (top + h / 2) / height, w / width, h / height]  # xywh normalized

            # class
            cls = label['value']  # class name
            if cls not in names:
                names.append(cls)

            line = names.index(cls), *xywh  # YOLO format (class_index, xywh)
            with open(label_path, 'a') as f:
                f.write(('%g ' * len(line)).rstrip() % line + '\n')

    # Save dataset.yaml
    d = {'path': f"../datasets/{file.stem}  # dataset root dir",
         'train': "images/train  # train images (relative to path) 128 images",
         'val': "images/val  # val images (relative to path) 128 images",
         'test': " # test images (optional)",
         'nc': len(names),
         'names': names}  # dictionary

    with open(save_dir / file.with_suffix('.yaml').name, 'w') as f:
        yaml.dump(d, f, sort_keys=False)

    # Zip
    if zip:
        print(f'Zipping as {save_dir}.zip...')
        os.system(f'zip -qr {save_dir}.zip {save_dir}')

    print('Conversion completed successfully!')


if __name__ == '__main__':
    convert('export-2021-06-29T15_25_41.934Z.json')

I have tried to run the script but I get the following error:

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
Cell In[6], line 10
      7 from PIL import Image
      8 from tqdm import tqdm
---> 10 from utils import make_dirs

ImportError: cannot import name 'make_dirs' from 'utils' (C:\Users\fores\anaconda3\lib\site-packages\utils\__init__.py)

Is possible to give a local directory in my machine and not call make_dirs(file.stem)? Please, any help with it?

I'd like to convert my label file in *json to YOLO * txt with to class ('bsb','wsb') using the labelbox_json2yolo.py.

In my data (image and label file) I have:

file = "https://raw.githubusercontent.com/Leprechault/trash/main/YT_EMBRAPA_002.zip" # Patch to zip file in GitHub

import json
import os
from pathlib import Path

import requests
import yaml
from PIL import Image
from tqdm import tqdm

from utils import make_dirs


def convert(file, zip=True):
    # Convert Labelbox JSON labels to YOLO labels
    names = ['bsb','wsb']  # class names
    file = Path(file)
    save_dir = make_dirs(file.stem)
    with open(file) as f:
        data = json.load(f)  # load JSON

    for img in tqdm(data, desc=f'Converting {file}'):
        im_path = img['Labeled Data']
        im = Image.open(requests.get(im_path, stream=True).raw if im_path.startswith('http') else im_path)  # open
        width, height = im.size  # image size
        label_path = save_dir / 'labels' / Path(img['External ID']).with_suffix('.txt').name
        image_path = save_dir / 'images' / img['External ID']
        im.save(image_path, quality=95, subsampling=0)

        for label in img['Label']['objects']:
            # box
            top, left, h, w = label['bbox'].values()  # top, left, height, width
            xywh = [(left + w / 2) / width, (top + h / 2) / height, w / width, h / height]  # xywh normalized

            # class
            cls = label['value']  # class name
            if cls not in names:
                names.append(cls)

            line = names.index(cls), *xywh  # YOLO format (class_index, xywh)
            with open(label_path, 'a') as f:
                f.write(('%g ' * len(line)).rstrip() % line + '\n')

    # Save dataset.yaml
    d = {'path': f"../datasets/{file.stem}  # dataset root dir",
         'train': "images/train  # train images (relative to path) 128 images",
         'val': "images/val  # val images (relative to path) 128 images",
         'test': " # test images (optional)",
         'nc': len(names),
         'names': names}  # dictionary

    with open(save_dir / file.with_suffix('.yaml').name, 'w') as f:
        yaml.dump(d, f, sort_keys=False)

    # Zip
    if zip:
        print(f'Zipping as {save_dir}.zip...')
        os.system(f'zip -qr {save_dir}.zip {save_dir}')

    print('Conversion completed successfully!')


if __name__ == '__main__':
    convert('export-2021-06-29T15_25_41.934Z.json')
I have tried to run the script but I get the following error:

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
Cell In[6], line 10
      7 from PIL import Image
      8 from tqdm import tqdm
---> 10 from utils import make_dirs

ImportError: cannot import name 'make_dirs' from 'utils' (C:\Users\fores\anaconda3\lib\site-packages\utils\__init__.py)

Is possible to give a local directory in my machine and not call make_dirs(file.stem)? Please, any help with it?

if you download this repo, you will get utils.py which contains function make_dirs()

FYI, Take a look in this thread
ultralytics/yolov5#10621

Thanks @ichsan2895 !!

You're welcome! If you have any more questions or need further assistance, feel free to ask. Good luck with your project!