-
Notifications
You must be signed in to change notification settings - Fork 2
/
vott2.0_to_yolo.py
124 lines (107 loc) · 4.03 KB
/
vott2.0_to_yolo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""Convert the annotations from using VoTT 2.0 labeling tool
to YOLO text format for this project.
Also, creates a test.txt and train.txt file with paths
to test and train images."""
import argparse
import json
import glob
import os
import random
# Change to match your labels and give a unique number starting at 0
LABELS = {'helmet': 0, 'no_helmet': 1}
def convert2yolo(annotarray, origwidth, origheight):
"""
Convert VoTT json format to yolo
height,width,left,top --> x_center,y_center,width,height
* NOTE: the "top" here is distance from the top.
Arguments
---------
annotarray : list
[height,width,left,top]
Returns
-------
list
bounding box in format [x_center,y_center,width,height]
"""
boxheight = float(annotarray[0])
boxwidth = float(annotarray[1])
boxleft = float(annotarray[2])
boxtop = float(annotarray[3])
# Calculate x center and y center, then scale 0-1
x_center = (boxleft + (0.5*boxwidth))/origwidth
y_center = (boxtop + (0.5*boxheight))/origheight
# Scale box width, height to 0-1
boxwidth, boxheight = boxwidth/origwidth, boxheight/origheight
return [x_center, y_center, boxwidth, boxheight]
def getannot(annotdict):
"""
Convert the json annot for one image to proper yolo format
* NOTE: the "top" here is distance from the top.
Arguments
---------
annotdict : dict
json dictionary with data for one image
"""
filename = annotdict['asset']['name']
origwidth = annotdict['asset']['size']['width']
origheight = annotdict['asset']['size']['height']
regions = annotdict['regions']
regions2 = []
for r in regions:
label = LABELS[r['tags'][0]] #Should only be one
bbox = r['boundingBox']
h = bbox['height']
w = bbox['width']
left = bbox['left']
top = bbox['top'] # distance from top
yoloarray = [label]
yoloarray.extend(convert2yolo([h, w, left, top], origwidth, origheight))
regions2.append(yoloarray)
return regions2, filename
def extractannots(filelist, outdir):
"""Operates over all json files to extract annotations
Writes the yolo format .txt files to specified location"""
justfilenames = []
for file in filelist:
with open(file, 'r') as fptr:
filedata = json.load(fptr)
yoloregions, filename = getannot(filedata)
ending = filename.split('.')[-1]
with open(os.path.join(outdir, filename.replace(ending, 'txt')), 'w') as fptr:
for annot in yoloregions:
annot = [str(a) for a in annot]
fptr.write(' '.join(annot) + '\n')
justfilenames.append(filename)
trainset = []
testset = []
for f in justfilenames:
r = random.choice(range(10))
if r < 2:
testset.append(os.path.join('data', 'obj', f))
else:
trainset.append(os.path.join('data', 'obj', f))
with open('train.txt', 'w') as fptr:
for samp in trainset:
fptr.write(samp + '\n')
with open('test.txt', 'w') as fptr:
for samp in testset:
fptr.write(samp + '\n')
if __name__ == "__main__":
"""Main"""
# For command line options
parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
# There should be one "asset.json" for each image with annotations
parser.add_argument(
'--annot-folder', type=str, dest='annot_folder', default='vott',
help='Annotations folder from VoTT 2.0 json format export'
)
# There should be one "asset.json" for each image with annotations
parser.add_argument(
'--out-folder', type=str, dest='out_folder', default='convert_out',
help='Output folder - will overwrite!'
)
args = parser.parse_args()
json_annot_files = glob.glob(os.path.join(args.annot_folder, '*-asset.json'))
if not os.path.exists(args.out_folder):
os.makedirs(args.out_folder)
extractannots(json_annot_files, args.out_folder)