├── README.md ├── generate_json.py └── open_json_file.py /README.md: -------------------------------------------------------------------------------- 1 | # Generate Annotations JSON Format for CreateML with Python 2 | 3 | Python script which generates annotations in JSON format required for training object detection models using CreateML. 4 | 5 | CreateML requires a list of dictionaries with information about the selected bounding boxes: center and size (height and width) of the bounding box. 6 | 7 | 8 | ![annotations](https://user-images.githubusercontent.com/41980160/60399956-b2af1700-9b32-11e9-990d-c0dc039273ad.png) 9 | 10 | 11 | ## Code Description 12 | 13 | The following code shows how to draw bounding boxes using matplotlib library. It iterates over the images of a folder and draws bounding boxes to get the center coodinates, heitgh and width of the bounding box. 14 | 15 | Detailed description on: https://medium.com/@eriksols/generate-annotations-json-format-for-createml-apple-with-python-90fc848cd439?postPublishedType=repub 16 | 17 | 18 | ## Run Script 19 | 20 | Pass the path to the images folder (image_folder = 'path_to_image_folder'). Each image must be named with the corresponding class in order to detect the label, example: 'dog_01.jpg'. 21 | 22 | ![folder_exm](https://user-images.githubusercontent.com/41980160/60400005-7af49f00-9b33-11e9-854b-700d0bedf4aa.png) 23 | 24 | ### Run generate_json.py script 25 | 26 | Code will iterate over all the images contained on the images folder. 27 | 28 | Now, you must draw the bounding box over the interest object. Once you are confident about the drawn bounding box, press "q" to generate and store the corresponding dictionary and continue the process with the next image. 29 | 30 | ![bb](https://user-images.githubusercontent.com/41980160/60400013-9f507b80-9b33-11e9-9627-bf4b68558a1a.png) 31 | 32 | A list containing the dictionaries of all images will be generated. 33 | 34 | ![dict](https://user-images.githubusercontent.com/41980160/60400020-b68f6900-9b33-11e9-94f7-b794d1dfb74f.png) 35 | 36 | Finally a JSON file will be generated. 37 | 38 | ![json_file](https://user-images.githubusercontent.com/41980160/60400025-cc9d2980-9b33-11e9-9c7e-3afe755b6384.png) 39 | 40 | 41 | ### Open and Iterate JSON file 42 | 43 | #### Run open_json_file.py 44 | 45 | This script opens and iterates over the list containing the image dictionaries. This script also shows how to access the the list elements and the corresponding dictionaries. 46 | 47 | It prints: 48 | List length (number of contained dictionaries) 49 | Image dictionary 50 | Label dictionary 51 | Coordinates dictionary 52 | 53 | ![res](https://user-images.githubusercontent.com/41980160/60400071-7d0b2d80-9b34-11e9-825d-0fecb61c483b.png) 54 | 55 | 56 | That's all! :D 57 | -------------------------------------------------------------------------------- /generate_json.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | import json 4 | import numpy as np 5 | import matplotlib.pyplot as plt 6 | from matplotlib.widgets import RectangleSelector 7 | 8 | 9 | def line_select_callback(clk, rls): 10 | global tl_list 11 | global br_list 12 | tl_list.append((int(clk.xdata), (int(clk.ydata)))) 13 | br_list.append((int(rls.xdata), (int(rls.ydata)))) 14 | 15 | 16 | def toggle_selector(event): 17 | toggle_selector.RS.set_active(True) 18 | 19 | 20 | def onkeypress(event): 21 | global tl_list 22 | global br_list 23 | if event.key == 'q': 24 | generate_json(tl_list, br_list) 25 | tl_list = [] 26 | br_list = [] 27 | 28 | 29 | def generate_json(tl_list, br_list): 30 | image_dict = {"image":'', "annotations":[]} 31 | label_dict = {"label":'', "coordinates":{}} 32 | coord_dict = {"x":int, "y":int, "width":int, "height":int} 33 | 34 | center_x = int(abs((tl_list[0][0] - br_list[0][0])/2)) + int(tl_list[0][0]) 35 | center_y = int(abs((tl_list[0][1] - br_list[0][1])/2)) + int(tl_list[0][1]) 36 | 37 | width = int(abs(tl_list[0][0] - br_list[0][0])) 38 | height = int(abs(tl_list[0][1] - br_list[0][1])) 39 | 40 | coord_dict['x'] = center_x 41 | coord_dict['y'] = center_y 42 | coord_dict['width'] = width 43 | coord_dict['height'] = height 44 | 45 | label_dict['label'] = name_class 46 | label_dict['coordinates'] = coord_dict 47 | 48 | image_dict['image'] = file_name 49 | image_dict['annotations'].append(label_dict) 50 | 51 | annotations.append(image_dict) 52 | 53 | 54 | #Main 55 | image_folder = 'path_to_image_folder' 56 | file_name = '' 57 | name_class = '' 58 | rotation = '' 59 | 60 | annotations = [] 61 | tl_list = [] 62 | br_list = [] 63 | file_names = os.listdir(image_folder) 64 | 65 | for file_name in file_names: 66 | if file_name[0] != '.': 67 | name_class, sep, tail = file_name.partition('_') 68 | dir_file = image_folder + '/' + file_name 69 | 70 | fig, ax = plt.subplots(1) 71 | image = cv2.imread(dir_file) 72 | image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 73 | ax.imshow(image) 74 | 75 | toggle_selector.RS = RectangleSelector( 76 | ax, line_select_callback, 77 | drawtype='box', useblit=True, 78 | button=[1], minspanx=5, minspany=5, 79 | spancoords='pixels', interactive=True 80 | ) 81 | 82 | bbox = plt.connect('key_press_event', toggle_selector) 83 | key = plt.connect('key_press_event', onkeypress) 84 | plt.show() 85 | 86 | print('Number of Processed Images:', len(annotations)) 87 | 88 | json_file = json.dumps(annotations) 89 | with open('save_directory/Annotations.json', 'w') as f: 90 | f.write(json_file) 91 | -------------------------------------------------------------------------------- /open_json_file.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | filename = 'path_to/annotations.json' 4 | 5 | with open(filename, 'r') as f: 6 | datastore = json.load(f) 7 | 8 | #Use the new datastore datastructure 9 | print(len(datastore)) 10 | print(datastore) 11 | print('\n') 12 | 13 | for dictionary in datastore: 14 | print(dictionary) 15 | print('\n') 16 | print(dictionary['annotations']) 17 | print('\n') 18 | print(dictionary['annotations'][0]['label']) 19 | print('\n') 20 | print(dictionary['annotations'][0]['coordinates']) 21 | print('\n') 22 | print(dictionary['annotations'][0]['coordinates']['x']) 23 | print(dictionary['annotations'][0]['coordinates']['y']) 24 | print(dictionary['annotations'][0]['coordinates']['width']) 25 | print(dictionary['annotations'][0]['coordinates']['height']) 26 | print('\n') 27 | --------------------------------------------------------------------------------