From bd2805da95c469d5c42df1074ec1c1f50ed38614 Mon Sep 17 00:00:00 2001 From: Jitske de Vries Date: Tue, 22 Sep 2020 15:34:12 +0200 Subject: [PATCH 1/7] Change for new Labelbox JSON format --- run.py | 129 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 99 insertions(+), 30 deletions(-) diff --git a/run.py b/run.py index f8f1b38..f54ab5a 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): @@ -19,45 +22,114 @@ def convert_labelbox_json(name, file): # 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']) + + 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) # filename 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'])) + # # shapes + # with open(name + '.shapes', 'a') as file: + # file.write('%g, %g\n' % (x['width'], x['height'])) - # Write *.names file - for x in tqdm(data['categories'], desc='Names'): - with open(name + '.names', 'a') as file: - file.write('%s\n' % x['name']) + # # Write *.names file + # for x in tqdm(data['categories'], desc='Names'): + # with open(name + '.names', 'a') as file: + # file.write('%s\n' % x['name']) + # Write labels file + object_names = [] + for x in tqdm(data, desc='Names'): + labels = x['Label'] + + # 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 txt file + with open(name + '.names', 'a') as file: + for x in object_names: + file.write(x + '\n') + # 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 + print(object_name_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' + print(info_string) + + 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) # 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 +405,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 +426,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') From 7910819e3471f657ac32c7eed8e7fcc2b6518480 Mon Sep 17 00:00:00 2001 From: Jitske de Vries Date: Tue, 22 Sep 2020 15:37:56 +0200 Subject: [PATCH 2/7] Add how to run part to README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) 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) From 12e1d453e5d73b350d5eff28d0d3ef5fdd53f2da Mon Sep 17 00:00:00 2001 From: Jitske de Vries Date: Tue, 22 Sep 2020 15:49:56 +0200 Subject: [PATCH 3/7] Remove print statements and change directory output --- run.py | 19 ++++++------------- utils.py | 2 +- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/run.py b/run.py index f54ab5a..9b35709 100644 --- a/run.py +++ b/run.py @@ -19,6 +19,9 @@ def convert_labelbox_json(name, file): with open(file) as f: data = json.load(f) + # TODO: remove this! + data = data[0:20] + # Write images and shapes name = 'out' + os.sep + name file_id, file_name, width, height = [], [], [], [] @@ -55,19 +58,11 @@ def convert_labelbox_json(name, file): width.append(width_img) height.append(height_img) - # filename + # 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'])) - - # # Write *.names file - # for x in tqdm(data['categories'], desc='Names'): - # with open(name + '.names', 'a') as file: - # file.write('%s\n' % x['name']) - # Write labels file + # Gather all object names object_names = [] for x in tqdm(data, desc='Names'): labels = x['Label'] @@ -84,7 +79,7 @@ def convert_labelbox_json(name, file): # Sort alphabetically object_names.sort() - # Store names in txt file + # Store names in .names file with open(name + '.names', 'a') as file: for x in object_names: file.write(x + '\n') @@ -104,7 +99,6 @@ def convert_labelbox_json(name, file): # Extract object name object_name = y['value'] object_name_index = object_names.index(object_name) # image index - print(object_name_index) # Extract bounding box values + scale them with the width and height of image bbox = y['bbox'] @@ -120,7 +114,6 @@ def convert_labelbox_json(name, file): 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' - print(info_string) if (width_box > 0.) and (height_box > 0.): # if w > 0 and h > 0 with open('out/labels/' + label_name, 'a') as file: 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): From 5de75e96dc132d9fa4d82b5dfcea83609e05c9a3 Mon Sep 17 00:00:00 2001 From: Jitske de Vries Date: Tue, 22 Sep 2020 15:51:04 +0200 Subject: [PATCH 4/7] Remove data[0:10] --- run.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/run.py b/run.py index 9b35709..3d7e42d 100644 --- a/run.py +++ b/run.py @@ -19,9 +19,6 @@ def convert_labelbox_json(name, file): with open(file) as f: data = json.load(f) - # TODO: remove this! - data = data[0:20] - # Write images and shapes name = 'out' + os.sep + name file_id, file_name, width, height = [], [], [], [] From a560693ac69cf0556addcb79d1cec4a5db4cc16e Mon Sep 17 00:00:00 2001 From: Jitske de Vries Date: Wed, 30 Sep 2020 10:02:03 +0200 Subject: [PATCH 5/7] Add run.py --- run.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/run.py b/run.py index 3d7e42d..68f103a 100644 --- a/run.py +++ b/run.py @@ -19,6 +19,9 @@ 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 = [], [], [], [] @@ -80,7 +83,11 @@ def convert_labelbox_json(name, 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, desc='Annotations'): @@ -116,6 +123,19 @@ def convert_labelbox_json(name, file): 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) print('Done. Output saved to %s' % (os.getcwd() + os.sep + path)) From 791201221399c6268f15a538c48821a61442d961 Mon Sep 17 00:00:00 2001 From: Jitske de Vries Date: Wed, 30 Sep 2020 10:18:59 +0200 Subject: [PATCH 6/7] Backup --- backup/LICENSE | 21 +++++++++++++++++++++ backup/README.md | 21 +++++++++++++++++++++ backup/zed-opencv-native | 1 + 3 files changed, 43 insertions(+) create mode 100644 backup/LICENSE create mode 100644 backup/README.md create mode 160000 backup/zed-opencv-native diff --git a/backup/LICENSE b/backup/LICENSE new file mode 100644 index 0000000..73d8007 --- /dev/null +++ b/backup/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Stereolabs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. 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 From cd032753b7bfcd0b8711fc52789c7be71c273879 Mon Sep 17 00:00:00 2001 From: Glenn Jocher Date: Fri, 2 Jul 2021 14:49:54 +0200 Subject: [PATCH 7/7] Delete LICENSE License changes from GPL to MIT are prohibited. --- backup/LICENSE | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 backup/LICENSE diff --git a/backup/LICENSE b/backup/LICENSE deleted file mode 100644 index 73d8007..0000000 --- a/backup/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Stereolabs - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE.