Skip to content

Commit 832a50f

Browse files
committed
minor changes
1 parent 4430cac commit 832a50f

File tree

10 files changed

+120
-55
lines changed

10 files changed

+120
-55
lines changed

superannotate/input_converters/converters/coco_converters/coco_api.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,18 +102,11 @@ def _area(bitmask):
102102

103103

104104
def _toBbox(bitmask):
105-
contours, _ = cv2.findContours(
106-
bitmask.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE
107-
)
108-
segments = []
109-
for contour in contours:
110-
contour = contour.flatten().tolist()
111-
segments += contour
112-
113-
xmin = min(segments[::2])
114-
xmax = max(segments[::2])
115-
ymin = min(segments[1::2])
116-
ymax = max(segments[1::2])
105+
y, x = np.where(bitmask)
106+
xmin = int(min(x))
107+
xmax = int(max(x))
108+
ymin = int(min(y))
109+
ymax = int(max(y))
117110

118111
return [xmin, ymin, xmax - xmin + 1, ymax - ymin + 1]
119112

superannotate/input_converters/converters/coco_converters/coco_strategies.py

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -236,12 +236,15 @@ def sa_to_output_format(self):
236236

237237
out_json['annotations'] = annotations
238238
out_json['images'] = images
239-
json_data = json.dumps(out_json, indent=4)
240-
with open(
241-
self.output_dir / '{}.json'.format(self.dataset_name), 'w+'
242-
) as coco_json:
239+
write_to_json(
240+
self.output_dir / '{}.json'.format(self.dataset_name), out_json
241+
)
242+
# json_data = json.dumps(out_json, indent=4)
243+
# with open(
244+
# self.output_dir / '{}.json'.format(self.dataset_name), 'w+'
245+
# ) as coco_json:
243246

244-
coco_json.write(json_data)
247+
# coco_json.write(json_data)
245248

246249
self.set_num_converted(len(jsons))
247250

@@ -309,11 +312,9 @@ def sa_to_output_format(self):
309312
out_json['annotations'] = annotations
310313
out_json['images'] = images
311314

312-
json_data = json.dumps(out_json, indent=4)
313-
with open(
314-
self.output_dir / '{}.json'.format(self.dataset_name), 'w+'
315-
) as coco_json:
316-
coco_json.write(json_data)
315+
write_to_json(
316+
self.output_dir / '{}.json'.format(self.dataset_name), out_json
317+
)
317318
print("NUMBER OF IMAGES FAILED TO CONVERT", self.failed_conversion_cnt)
318319

319320
self.set_num_converted(len(jsons))
@@ -366,11 +367,14 @@ def sa_to_output_format(self):
366367
out_json['categories'] = res[0]
367368
out_json['annotations'] = res[1]
368369
out_json['images'] = res[2]
369-
json_data = json.dumps(out_json, indent=4)
370+
write_to_json(
371+
self.output_dir / '{}.json'.format(self.dataset_name), out_json
372+
)
373+
# json_data = json.dumps(out_json, indent=4)
370374

371-
with open(
372-
self.output_dir / '{}.json'.format(self.dataset_name), 'w+'
373-
) as coco_json:
374-
coco_json.write(json_data)
375+
# with open(
376+
# self.output_dir / '{}.json'.format(self.dataset_name), 'w+'
377+
# ) as coco_json:
378+
# coco_json.write(json_data)
375379

376380
self.set_num_converted(len(out_json['images']))

superannotate/input_converters/converters/labelbox_converters/labelbox_helper.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
import requests
21
import logging
2+
import requests
33

44
logger = logging.getLogger("superannotate-python-sdk")
55

66

77
def image_downloader(url, file_name):
8-
logger.info("Downloading mask for {}".format(file_name))
98
r = requests.get(url, stream=True)
10-
with open(file_name, 'wb') as f:
11-
f.write(r.content)
9+
if r.status_code == 200:
10+
with open(file_name, 'wb') as f:
11+
f.write(r.content)
12+
return True
13+
return False
1214

1315

1416
def _create_classes_id_map(json_data):

superannotate/input_converters/converters/labelbox_converters/labelbox_strategies.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import json
2-
import cv2
32

43
from ..baseStrategy import baseStrategy
54

@@ -14,9 +13,14 @@ def to_sa_format(self):
1413
json_data = json.load(
1514
open(self.export_root / (self.dataset_name + '.json'))
1615
)
17-
classes = self.conversion_algorithm(
18-
json_data, self.output_dir, self.task
19-
)
16+
if self.project_type == 'Vector':
17+
classes = self.conversion_algorithm(
18+
json_data, self.output_dir, self.task
19+
)
20+
elif self.project_type == 'Pixel':
21+
classes = self.conversion_algorithm(
22+
json_data, self.output_dir, self.export_root
23+
)
2024
sa_classes = self._create_classes(classes)
2125
(self.output_dir / 'classes').mkdir(exist_ok=True)
2226
write_to_json(self.output_dir / 'classes' / 'classes.json', sa_classes)

superannotate/input_converters/converters/labelbox_converters/labelbox_to_sa_pixel.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
from ....common import hex_to_rgb, blue_color_generator, write_to_json
1212

1313

14-
def labelbox_instance_segmentation_to_sa_pixel(json_data, output_dir, task=''):
14+
def labelbox_instance_segmentation_to_sa_pixel(
15+
json_data, output_dir, input_dir
16+
):
1517
classes = _create_classes_id_map(json_data)
1618
for data in json_data:
1719
file_name = data['External ID'] + '___pixel.json'
@@ -38,8 +40,17 @@ def labelbox_instance_segmentation_to_sa_pixel(json_data, output_dir, task=''):
3840
) or 'line' in instance.keys() or 'point' in instance.keys():
3941
continue
4042

41-
image_downloader(instance['instanceURI'], mask_name)
42-
mask = cv2.imread(mask_name)
43+
bitmask_name = '%s.png' % instance['featureId']
44+
downloaded = image_downloader(instance['instanceURI'], bitmask_name)
45+
if downloaded:
46+
mask = cv2.imread(bitmask_name)
47+
else:
48+
mask = cv2.imread(str(input_dir / 'bitmasks' / bitmask_name))
49+
bitmask_name = output_dir / bitmask_name
50+
51+
if isinstance(mask, type(None)):
52+
continue
53+
4354
if i == 0:
4455
H, W, _ = mask.shape
4556
sa_metadata['width'] = W
@@ -52,7 +63,7 @@ def labelbox_instance_segmentation_to_sa_pixel(json_data, output_dir, task=''):
5263
sa_obj = _create_pixel_instance(parts, attributes, class_name)
5364

5465
sa_instances.append(sa_obj.copy())
55-
Path(mask_name).unlink()
66+
Path(bitmask_name).unlink()
5667

5768
sa_json = _create_sa_json(sa_instances, sa_metadata)
5869
write_to_json(output_dir / file_name, sa_json)

superannotate/input_converters/converters/voc_converters/voc_helper.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,22 @@ def _get_voc_instances_from_xml(file_path):
1010
voc_instances = []
1111
for instance in instances:
1212
class_name = instance.find("name").text
13+
class_attributes = []
14+
for attr in ['pose', 'occluded', 'difficult', 'truncated']:
15+
attr_value = instance.find(attr)
16+
if attr_value is not None:
17+
class_attributes.append(
18+
{
19+
'name': attr_value.text,
20+
'groupName': attr
21+
}
22+
)
23+
1324
bbox = instance.find("bndbox")
1425
bbox = [
1526
float(bbox.find(x).text) for x in ["xmin", "ymin", "xmax", "ymax"]
1627
]
17-
voc_instances.append((class_name, bbox))
28+
voc_instances.append(({class_name: class_attributes}, bbox))
1829
return voc_instances
1930

2031

superannotate/input_converters/converters/voc_converters/voc_strategies.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,40 @@ def to_sa_format(self):
2121
if '___save.png' not in str(file.name):
2222
(self.output_dir / file.name).unlink()
2323

24-
def _create_classes(self, classes):
24+
def _create_classes(self, instances):
25+
classes = {}
26+
for instance in instances:
27+
for class_, value in instance.items():
28+
if class_ not in classes:
29+
classes[class_] = {}
30+
31+
for attr in value:
32+
if attr['groupName'] in classes[class_]:
33+
classes[class_][attr['groupName']].append(attr['name'])
34+
else:
35+
classes[class_][attr['groupName']] = [attr['name']]
36+
2537
sa_classes = []
26-
for class_ in set(classes):
38+
for class_ in classes:
2739
color = np.random.choice(range(256), size=3)
2840
hexcolor = "#%02x%02x%02x" % tuple(color)
41+
attribute_groups = []
42+
for attr_group, value in classes[class_].items():
43+
attributes = []
44+
for attr in set(value):
45+
attributes.append({'name': attr})
46+
47+
attribute_groups.append(
48+
{
49+
'name': attr_group,
50+
'is_multiselect': 0,
51+
'attributes': attributes
52+
}
53+
)
2954
sa_class = {
3055
"name": class_,
3156
"color": hexcolor,
32-
"attribute_groups": []
57+
"attribute_groups": attribute_groups
3358
}
3459
sa_classes.append(sa_class)
3560
return sa_classes

superannotate/input_converters/converters/voc_converters/voc_to_sa_pixel.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,15 @@ def _generate_instances(polygon_instances, voc_instances, bluemask_colors):
5959
for _, bbox in voc_instances:
6060
ious.append(_iou(bbox_poly, bbox))
6161
ind = np.argmax(ious)
62+
class_name = list(voc_instances[ind][0].keys())[0]
63+
attributes = voc_instances[ind][0][class_name]
6264
instances.append(
6365
{
6466
"className": voc_instances[ind][0],
6567
"polygon": polygon,
6668
"bbox": voc_instances[ind][1],
67-
"blue_color": bluemask_colors[i]
69+
"blue_color": bluemask_colors[i],
70+
'classAttributes': attributes
6871
}
6972
)
7073
i += 1
@@ -83,16 +86,20 @@ def voc_instance_segmentation_to_sa_pixel(voc_root, output_dir):
8386
voc_instances = _get_voc_instances_from_xml(
8487
annotation_dir / filename.name
8588
)
89+
for class_, _ in voc_instances:
90+
classes.append(class_)
91+
8692
maped_instances = _generate_instances(
8793
polygon_instances, voc_instances, bluemask_colors
8894
)
8995

9096
sa_instances = []
9197
for instance in maped_instances:
9298
parts = [{"color": instance["blue_color"]}]
93-
sa_obj = _create_pixel_instance(parts, [], instance["className"])
99+
sa_obj = _create_pixel_instance(
100+
parts, instance['classAttributes'], instance["className"]
101+
)
94102
sa_instances.append(sa_obj)
95-
classes.append(instance['className'])
96103

97104
file_name = "%s.jpg___pixel.json" % (filename.stem)
98105
sa_metadata = {'name': filename.stem}

superannotate/input_converters/converters/voc_converters/voc_to_sa_vector.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,15 @@ def _generate_instances(polygon_instances, voc_instances):
6262
ious.append(_iou(bbox_poly, bbox))
6363
ind = np.argmax(ious)
6464
for poly in polygon:
65+
class_name = list(voc_instances[ind][0].keys())[0]
66+
attributes = voc_instances[ind][0][class_name]
6567
instances.append(
6668
{
67-
'className': voc_instances[ind][0],
69+
'className': class_name,
6870
'polygon': poly,
6971
'bbox': voc_instances[ind][1],
70-
'groupId': group_id
72+
'groupId': group_id,
73+
'classAttributes': attributes
7174
}
7275
)
7376
return instances
@@ -84,16 +87,18 @@ def voc_instance_segmentation_to_sa_vector(voc_root, output_dir):
8487
voc_instances = _get_voc_instances_from_xml(
8588
annotation_dir / filename.name
8689
)
90+
for class_, _ in voc_instances:
91+
classes.append(class_)
92+
8793
maped_instances = _generate_instances(polygon_instances, voc_instances)
8894
sa_instances = []
8995
for instance in maped_instances:
9096
sa_obj = _create_vector_instance(
91-
'polygon', instance["polygon"], {}, [], instance["className"]
97+
'polygon', instance["polygon"], {}, instance['classAttributes'],
98+
instance["className"]
9299
)
93100
sa_instances.append(sa_obj)
94101

95-
classes.append(instance["className"])
96-
97102
file_name = "%s.jpg___objects.json" % filename.stem
98103
sa_metadata = {'name': filename.stem}
99104
sa_json = _create_sa_json(sa_instances, sa_metadata)
@@ -110,11 +115,14 @@ def voc_object_detection_to_sa_vector(voc_root, output_dir):
110115
annotation_dir / filename.name
111116
)
112117
sa_instances = []
113-
for class_name, bbox in voc_instances:
114-
classes.append(class_name)
118+
for class_, bbox in voc_instances:
119+
class_name = list(class_.keys())[0]
120+
classes.append(class_)
115121

116122
points = (bbox[0], bbox[1], bbox[2], bbox[3])
117-
sa_obj = _create_vector_instance('bbox', points, {}, [], class_name)
123+
sa_obj = _create_vector_instance(
124+
'bbox', points, {}, class_[class_name], class_name
125+
)
118126
sa_instances.append(sa_obj)
119127

120128
file_name = "%s.jpg___objects.json" % filename.stem

tests/test_preannotation_upload_cli.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def test_preannotation_folder_upload_download_cli_pixel_object_COCO(tmpdir):
171171
shell=True
172172
)
173173
time.sleep(5)
174-
count_in = 6
174+
count_in = 3
175175

176176
images = sa.search_images(project)
177177
for image_name in images:

0 commit comments

Comments
 (0)