-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcoco2sloth.py
More file actions
executable file
·127 lines (98 loc) · 3.45 KB
/
coco2sloth.py
File metadata and controls
executable file
·127 lines (98 loc) · 3.45 KB
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
125
126
127
#!/usr/bin/env python3
"""
Convert COCO human bounding boxes to Sloth JSON format
"""
import os
import sys
import json
from sloth_common import getJson
def getNames(data, classMap={}):
"""
Returns dictionary { 1: "person", 2: "bicycle", ... }
Swaps names to what's in classMap, if provided
"""
names = {}
for c in data["categories"]:
if c["name"] in classMap:
names[c["id"]] = classMap[c["name"]]
else:
names[c["id"]] = c["name"]
return names
def getFilenames(data, imagePath):
"""
Returns dictionary { "img id 1": "imagePath/filename 1", ... }
"""
filenames = {}
for img in data["images"]:
filenames[img["id"]] = os.path.join(imagePath, img["file_name"])
return filenames
def getBoundingBoxes(data):
"""
Returns dictionary { "img id 1": [ (x,y,w,h), (x,y,w,y), ... ], ...}
"""
boundingBoxes = {}
for a in data["annotations"]:
imageId = a["image_id"]
categoryId = a["category_id"]
x, y, w, h = a["bbox"]
# There can be more than one bounding box per image
if imageId not in boundingBoxes:
boundingBoxes[imageId] = []
boundingBoxes[imageId].append((categoryId, x, y, w, h))
return boundingBoxes
def generateSloth(filenames, boundingBoxes, classNames, includeClasses):
slothData = []
for imageId, imgBoxes in boundingBoxes.items():
# Generate each bounding box
annotations = []
for categoryId, x, y, w, h in imgBoxes:
className = classNames[categoryId]
if not includeClasses or className.lower() in includeClasses:
annotations.append({
"class": className,
"height": h,
"width": w,
"x": x,
"y": y
})
assert imageId in filenames, "Image ID not found in list of filenames!"
# Generate annotation for this image, but only if there are some
# bounding boxes for this image
if annotations:
slothData.append({
"annotations": annotations,
"class": "image",
"filename": filenames[imageId]
})
return slothData
def outputJson(data):
print(json.dumps(data, indent=4))
if __name__ == "__main__":
# Get JSON file
if len(sys.argv) != 3 and len(sys.argv) != 4:
#raise RuntimeError("coco2sloth.py person_keypoints_train2017.json path/to/images")
raise RuntimeError("coco2sloth.py instances_train2017.json path/to/images [human,bicycle,...]")
filename = sys.argv[1]
imagePath = sys.argv[2]
if len(sys.argv) == 4:
includeClasses = sys.argv[3].lower().split(",")
else:
includeClasses = [ "human" ]
# Load JSON file
data = getJson(filename)
# We've changed the names somewhat
classMap = {
"person": "human",
"cup": "glass"
} # bowl, chair
# Get dictionary mapping category id to class name
classNames = getNames(data, classMap)
# Get dictionary of image filenames by id, so we can easily find the
# filename
filenames = getFilenames(data, imagePath)
# Get bounding boxes for each image
boundingBoxes = getBoundingBoxes(data)
# Create Sloth JSON file
slothData = generateSloth(filenames, boundingBoxes, classNames, includeClasses)
# Output to stdout
outputJson(slothData)