diff --git a/README.md b/README.md index 6e044df..c90b136 100755 --- a/README.md +++ b/README.md @@ -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) diff --git a/backup/README.md b/backup/README.md new file mode 100644 index 0000000..44ab525 --- /dev/null +++ b/backup/README.md @@ -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. diff --git a/backup/zed-opencv-native b/backup/zed-opencv-native new file mode 160000 index 0000000..91acaeb --- /dev/null +++ b/backup/zed-opencv-native @@ -0,0 +1 @@ +Subproject commit 91acaeb66b8c09be47edc7cb49c51165eda43d81 diff --git a/run.py b/run.py index f8f1b38..68f103a 100644 --- a/run.py +++ b/run.py @@ -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): @@ -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 + 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 @@ -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', @@ -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') diff --git a/utils.py b/utils.py index 8b5e166..991ec7a 100644 --- a/utils.py +++ b/utils.py @@ -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):