Skip to content

Commit 4b51ef5

Browse files
committed
coverage increase
1 parent 0396650 commit 4b51ef5

File tree

20 files changed

+511
-164
lines changed

20 files changed

+511
-164
lines changed

superannotate/input_converters/conversion.py

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
('Pixel', 'panoptic_segmentation'),
2626
('Pixel', 'instance_segmentation'),
2727
('Vector', 'keypoint_detection'),
28-
('Vector', 'instance_segmentation')
28+
('Vector', 'instance_segmentation'), ('Vector', 'object_detection')
2929
],
3030
'VOC':
3131
[
@@ -168,7 +168,7 @@ def export_annotation_format(
168168
'Pixel' project creates <image_name>___pixel.jsons and <image_name>___save.png annotation mask for each image.
169169
:type project_type: str
170170
:param task: Task can be one of the following: ['panoptic_segmentation', 'instance_segmentation',
171-
'keypoint_detection', 'object_detection']. (Default: "objec_detection").
171+
'keypoint_detection', 'object_detection']. (Default: "object_detection").
172172
'keypoint_detection' can be used to converts keypoints from/to available annotation format.
173173
'panoptic_segmentation' will use panoptic mask for each image to generate bluemask for SuperAnnotate annotation format and use bluemask to generate panoptic mask for invert conversion. Panoptic masks should be in the input folder.
174174
'instance_segmentation' 'Pixel' project_type converts instance masks and 'Vector' project_type generates bounding boxes and polygons from instance masks. Masks should be in the input folder if it is 'Pixel' project_type.
@@ -258,11 +258,57 @@ def import_annotation_format(
258258
Vector vector_annotation
259259
============== ======================
260260
261+
============== ======================
262+
From VoTT to SA
263+
--------------------------------------
264+
project_type task
265+
============== ======================
266+
Vector instance_segmentation
267+
Vector object_detection
268+
Vector vector_annotation
269+
============== ======================
270+
271+
============== ======================
272+
From SageMaker to SA
273+
--------------------------------------
274+
project_type task
275+
============== ======================
276+
Pixel instance_segmentation
277+
Vector objcet_detection
278+
============== ======================
279+
280+
============== ======================
281+
From VGG to SA
282+
--------------------------------------
283+
project_type task
284+
============== ======================
285+
Vector instance_segmentation
286+
Vector object_detection
287+
Vector vector_annotation
288+
============== ======================
289+
290+
============== ======================
291+
From GoogleCloud to SA
292+
--------------------------------------
293+
project_type task
294+
============== ======================
295+
Vector object_detection
296+
============== ======================
297+
298+
============== ======================
299+
From YOLO to SA
300+
--------------------------------------
301+
project_type task
302+
============== ======================
303+
Vector object_detection
304+
============== ======================
305+
261306
:param input_dir: Path to the dataset folder that you want to convert.
262307
:type input_dir: str
263308
:param output_dir: Path to the folder, where you want to have converted dataset.
264309
:type output_dir: str
265-
:param dataset_format: Annotation format to convert SuperAnnotate annotation format. Available candidates are: ["COCO", "VOC", "LabelBox", "DataLoop", "Supervisely"]
310+
:param dataset_format: Annotation format to convert SuperAnnotate annotation format. Available candidates are: ["COCO", "VOC", "LabelBox", "DataLoop",
311+
"Supervisely", 'VGG', 'YOLO', 'SageMake', 'VoTT', 'GoogleCloud']
266312
:type dataset_format: str
267313
:param dataset_name: Name of the json file in the input_dir, which should be converted.
268314
:type dataset_name: str
@@ -271,7 +317,7 @@ def import_annotation_format(
271317
'Pixel' project creates <image_name>___pixel.jsons and <image_name>___save.png annotation mask for each image.
272318
:type project_type: str
273319
:param task: Task can be one of the following: ['panoptic_segmentation', 'instance_segmentation',
274-
'keypoint_detection', 'object_detection']. (Default: "objec_detection").
320+
'keypoint_detection', 'object_detection']. (Default: "object_detection").
275321
'keypoint_detection' can be used to converts keypoints from/to available annotation format.
276322
'panoptic_segmentation' will use panoptic mask for each image to generate bluemask for SuperAnnotate annotation format and use bluemask to generate panoptic mask for invert conversion. Panoptic masks should be in the input folder.
277323
'instance_segmentation' 'Pixel' project_type converts instance masks and 'Vector' project_type generates bounding boxes and polygons from instance masks. Masks should be in the input folder if it is 'Pixel' project_type.

superannotate/input_converters/converters/coco_converters/coco_strategies.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
)
1616
from .coco_to_sa_vector import (
1717
coco_instance_segmentation_to_sa_vector,
18-
coco_keypoint_detection_to_sa_vector
18+
coco_keypoint_detection_to_sa_vector, coco_object_detection_to_sa_vector
1919
)
2020
from .sa_pixel_to_coco import (
2121
sa_pixel_to_coco_instance_segmentation, sa_pixel_to_coco_object_detection,
@@ -136,7 +136,7 @@ def __setup_conversion_algorithm(self):
136136
if self.task == 'instance_segmentation':
137137
self.conversion_algorithm = coco_instance_segmentation_to_sa_vector
138138
elif self.task == 'object_detection':
139-
raise ValueError('Method not implemented')
139+
self.conversion_algorithm = coco_object_detection_to_sa_vector
140140

141141
def __str__(self, ):
142142
return '{} object'.format(self.name)

superannotate/input_converters/converters/coco_converters/coco_to_sa_pixel.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,28 @@
66
import pycocotools.mask as maskUtils
77
from panopticapi.utils import id2rgb
88
from tqdm import tqdm
9+
from pycocotools.coco import COCO
910

1011
from ....common import hex_to_rgb, blue_color_generator
1112

1213

14+
def _rle_to_polygon(coco_json, annotation):
15+
coco = COCO(coco_json)
16+
binary_mask = coco.annToMask(annotation)
17+
contours, hierarchy = cv2.findContours(
18+
binary_mask.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
19+
)
20+
segmentation = []
21+
22+
for contour in contours:
23+
contour = contour.flatten().tolist()
24+
if len(contour) > 4:
25+
segmentation.append(contour)
26+
if len(segmentation) == 0:
27+
continue
28+
return segmentation
29+
30+
1331
def coco_panoptic_segmentation_to_sa_pixel(coco_path, images_path):
1432
coco_json = json.load(open(coco_path))
1533
hex_colors = blue_color_generator(len(coco_json["categories"]))
@@ -75,7 +93,7 @@ def coco_instance_segmentation_to_sa_pixel(coco_path, images_path):
7593

7694
images_dict = {}
7795
for img in coco_json['images']:
78-
images_dict[img['id']] = {
96+
images_dict[str(img['id'])] = {
7997
'mask': np.zeros((img['height'], img['width'], 4)),
8098
'file_name': img['file_name'],
8199
'segments_num': 0
@@ -85,16 +103,28 @@ def coco_instance_segmentation_to_sa_pixel(coco_path, images_path):
85103
hexcolors = blue_color_generator(len(coco_json['annotations']))
86104
for i, annot in enumerate(coco_json['annotations']):
87105
if str(annot['image_id']) not in images_dict:
106+
print('check')
88107
continue
89108

90109
hexcolor = hexcolors[images_dict[str(annot['image_id'])]['segments_num']
91110
]
92111
color = hex_to_rgb(hexcolor)
93112
images_dict[str(annot['image_id'])]['segments_num'] += 1
94113

114+
if isinstance(annot['segmentation'], dict):
115+
annot['segmentation'] = _rle_to_polygon(coco_path, annot)
116+
117+
segment = annot['segmentation'][0]
118+
H, W, C = images_dict[str(annot['image_id'])]['mask'].shape
119+
bitmask = np.zeros((H, W)).astype(np.uint8)
120+
pts = np.array(
121+
[segment[2 * i:2 * (i + 1)] for i in range(len(segment) // 2)],
122+
dtype=np.int32
123+
)
124+
125+
cv2.fillPoly(bitmask, [pts], 1)
95126
images_dict[str(annot['image_id']
96-
)]['mask'][maskUtils.decode(annot['segmentation']) == 1
97-
] = list(color)[::-1] + [255]
127+
)]['mask'][bitmask == 1] = list(color)[::-1] + [255]
98128

99129
sa_obj = {
100130
"classId": annot['category_id'],
@@ -108,6 +138,7 @@ def coco_instance_segmentation_to_sa_pixel(coco_path, images_path):
108138
"attributeNames": [],
109139
"imageId": annot["image_id"]
110140
}
141+
111142
key = images_dict[str(annot['image_id'])]['file_name']
112143
if key not in sa_json.keys():
113144
sa_json[key] = []

0 commit comments

Comments
 (0)