Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert new Labelbox JSON format to YOLO #7

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ Python 3.7 or later with the following `pip3 install -U -r requirements.txt` pac
- `numpy`
- `tqdm`

# How to run
At the bottom of the run file, change the source into the JSON source you are using. Paste the JSON file name as the file name. Then just run the script:

``` python3 run.py ```

# Citation

[![DOI](https://zenodo.org/badge/186122711.svg)](https://zenodo.org/badge/latestdoi/186122711)
Expand Down
21 changes: 21 additions & 0 deletions backup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Stereolabs ZED - OpenCV Native Capture

This sample shows how to capture rectified images with the ZED or ZED-M Camera and OpenCV, without the ZED SDK.

If you want to use OpenCV with the ZED SDK features, check our sample [here](https://github.com/stereolabs/zed-opencv).

## OS

- Windows, Linux, MacOS

### How to use in C++

Please refer to instructions in [cpp folder](./cpp)

### How to use in Python

Please refer to instructions in [python folder](./python)

## Notes

- You need to know the serial number of the camera you are trying to open. To do so, you can use ZED Explorer tools (ZED SDK tools) and check the serial number on the top right of ZED Explorer window.
1 change: 1 addition & 0 deletions backup/zed-opencv-native
Submodule zed-opencv-native added at 91acae
141 changes: 110 additions & 31 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

from utils import *

import requests
import time


# Convert Labelbox JSON file into YOLO-format labels ---------------------------
def convert_labelbox_json(name, file):
Expand All @@ -16,48 +19,127 @@ def convert_labelbox_json(name, file):
with open(file) as f:
data = json.load(f)

# Do not use all data if you are debugging
data = data[0:30]

# Write images and shapes
name = 'out' + os.sep + name
file_id, file_name, width, height = [], [], [], []
for i, x in enumerate(tqdm(data['images'], desc='Files and Shapes')):
file_id.append(x['id'])
file_name.append('IMG_' + x['file_name'].split('IMG_')[-1])
width.append(x['width'])
height.append(x['height'])

# filename
for i, x in enumerate(tqdm(data, desc='Files')):

# Store file id
file_id.append(x['ID'])

# Download image
response = ''
url = x['Labeled Data']

while response == '':
try:
response = requests.get(url)
break
except:
print("Connection refused by the server..")
print("Let me sleep for 5 seconds")
print("ZZzzzz...")
time.sleep(5)
print("Was a nice sleep, now let me continue...")
continue

# Write image in out/image folder
file_name.append(x['External ID'])
image_file = open('out/images/' + file_name[i], 'wb')
image_file.write(response.content)
image_file.close()

# Store width and height of image
width_img, height_img = (Image.open('out/images/' + file_name[i])).size
width.append(width_img)
height.append(height_img)

# Make text file with all file names, you can use this as train.txt or valid.txt eventually
with open(name + '.txt', 'a') as file:
file.write('%s\n' % file_name[i])

# shapes
with open(name + '.shapes', 'a') as file:
file.write('%g, %g\n' % (x['width'], x['height']))
# Gather all object names
object_names = []
for x in tqdm(data, desc='Names'):
labels = x['Label']

# Write *.names file
for x in tqdm(data['categories'], desc='Names'):
with open(name + '.names', 'a') as file:
file.write('%s\n' % x['name'])
# Check whether there are any objects in the image
if 'objects' in labels:
objects = labels['objects']

for j, y in enumerate(objects):
# If the object name is unique, store in object_names
if y['value'] not in object_names:
object_names.append(y['value'])

# Sort alphabetically
object_names.sort()

# Store names in .names file
with open(name + '.names', 'a') as file:
for x in object_names:
file.write(x + '\n')

# Intitialize
smallest_width = 0
smallest_height = 0
smallest_area = 0

# Write labels file
for x in tqdm(data['annotations'], desc='Annotations'):
i = file_id.index(x['image_id']) # image index
for x in tqdm(data, desc='Annotations'):
i = file_id.index(x['ID']) # image index
label_name = Path(file_name[i]).stem + '.txt'

# The Labelbox bounding box format is [top left x, top left y, width, height]
box = np.array(x['bbox'], dtype=np.float64)
box[:2] += box[2:] / 2 # xy top-left corner to center
box[[0, 2]] /= width[i] # normalize x
box[[1, 3]] /= height[i] # normalize y
labels = x['Label']
objects = labels['objects']


for j, y in enumerate(objects):

if (box[2] > 0.) and (box[3] > 0.): # if w > 0 and h > 0
with open('out/labels/' + label_name, 'a') as file:
file.write('%g %.6f %.6f %.6f %.6f\n' % (x['category_id'] - 1, *box))
# Extract object name
object_name = y['value']
object_name_index = object_names.index(object_name) # image index

# Extract bounding box values + scale them with the width and height of image
bbox = y['bbox']
left = bbox['left']/width[i]
top = bbox['top']/height[i]
width_box = bbox['width']/width[i]
height_box = bbox['height']/height[i]

# Convert into YOLO format
# The Labelbox bounding box format is [top left x, top left y, width, height]
# The YOLO format is <object-class> <x_center> <y_center> <width> <height>
x_center = left + width_box/2
y_center = top + height_box/2

info_string = str(object_name_index) + ' ' + str(x_center) + ' ' + str(y_center) + ' ' + str(width_box) + ' ' + str(height_box) + '\n'

if (width_box > 0.) and (height_box > 0.): # if w > 0 and h > 0
with open('out/labels/' + label_name, 'a') as file:
file.write(info_string)

if (width_box*width[i]>smallest_width):
smallest_width = width_box*width[i]

if (height_box*height[i]>smallest_height):
smallest_height = height_box*height[i]

if (width_box*width[i]*height_box*height[i]>smallest_area):
smallest_area = width_box*width[i]*height_box*height[i]

print('Smallest area' + str(smallest_area) + '\n')
print('Smallest height' + str(smallest_height) + '\n')
print('Smallest width' + str(smallest_width) + '\n')

# Split data into train, test, and validate files
split_files(name, file_name)
# split_files(name, file_name)
print('Done. Output saved to %s' % (os.getcwd() + os.sep + path))


# Convert INFOLKS JSON file into YOLO-format labels ----------------------------
def convert_infolks_json(name, files, img_path):
# Create folders
Expand Down Expand Up @@ -333,11 +415,11 @@ def convert_coco_json(json_dir='../coco/annotations/'):


if __name__ == '__main__':
source = 'coco'
source = 'labelbox'

if source is 'labelbox': # Labelbox https://labelbox.com/
convert_labelbox_json(name='supermarket2',
file='../supermarket2/export-coco.json')
convert_labelbox_json(name='canals',
file='export-2020-09-22T13 19 20.867Z.json')

elif source is 'infolks': # Infolks https://infolks.info/
convert_infolks_json(name='out',
Expand All @@ -354,6 +436,3 @@ def convert_coco_json(json_dir='../coco/annotations/'):

elif source is 'coco':
convert_coco_json()

# zip results
# os.system('zip -r ../coco.zip ../coco')
2 changes: 1 addition & 1 deletion utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def split_indices(x, train=0.9, test=0.1, validate=0.0, shuffle=True): # split
return v[:i], v[i:j], v[j:k] # return indices


def make_folders(path='../out/'):
def make_folders(path='out/'):
# Create folders

if os.path.exists(path):
Expand Down