Skip to content

Commit 70ee77d

Browse files
authored
Merge pull request #728 from Labelbox/ms/coco-invalid-polygons
fix coco invalid polygons
2 parents 944ed30 + 6c845bc commit 70ee77d

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

labelbox/data/annotation_types/geometry/mask.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ def geometry(self) -> Dict[str, Tuple[int, int, int]]:
5454
external_polygons = self._extract_polygons_from_contours(
5555
external_contours)
5656
holes = self._extract_polygons_from_contours(holes)
57+
58+
if not external_polygons.is_valid:
59+
external_polygons = external_polygons.buffer(0)
60+
61+
if not holes.is_valid:
62+
holes = holes.buffer(0)
63+
5764
return external_polygons.difference(holes).__geo_interface__
5865

5966
def draw(self,
@@ -78,7 +85,6 @@ def draw(self,
7885
np.ndarray representing only this object
7986
as opposed to the mask that this object references which might have multiple objects determined by colors
8087
"""
81-
8288
mask = self.mask.value
8389
mask = np.alltrue(mask == self.color, axis=2).astype(np.uint8)
8490

labelbox/data/serialization/coco/instance_dataset.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ def mask_to_coco_object_annotation(
2121
# This is going to fill any holes into the multipolygon
2222
# If you need to support holes use the panoptic data format
2323
shapely = annotation.value.shapely.simplify(1).buffer(0)
24-
2524
if shapely.is_empty:
2625
return
2726

labelbox/data/serialization/coco/panoptic_dataset.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ def vector_to_coco_segment_info(canvas: np.ndarray,
2222
annotation: ObjectAnnotation,
2323
annotation_idx: int, image: CocoImage,
2424
category_id: int):
25+
2526
shapely = annotation.value.shapely
27+
if shapely.is_empty:
28+
return
29+
2630
xmin, ymin, xmax, ymax = shapely.bounds
2731
canvas = annotation.value.draw(height=image.height,
2832
width=image.width,
@@ -40,6 +44,9 @@ def mask_to_coco_segment_info(canvas: np.ndarray, annotation,
4044
color = id_to_rgb(annotation_idx)
4145
mask = annotation.value.draw(color=color)
4246
shapely = annotation.value.shapely
47+
if shapely.is_empty:
48+
return
49+
4350
xmin, ymin, xmax, ymax = shapely.bounds
4451
canvas = np.where(canvas == (0, 0, 0), mask, canvas)
4552
return SegmentInfo(id=annotation_idx,
@@ -70,20 +77,32 @@ def process_label(label: Label,
7077
for annotation_idx, annotation in enumerate(annotations[class_name]):
7178
categories[annotation.name] = hash_category_name(annotation.name)
7279
if isinstance(annotation.value, Mask):
73-
segment, canvas = (mask_to_coco_segment_info(
80+
coco_segment_info = mask_to_coco_segment_info(
7481
canvas, annotation, class_idx + 1,
75-
categories[annotation.name]))
82+
categories[annotation.name])
83+
84+
if coco_segment_info is None:
85+
# Filter out empty masks
86+
continue
87+
88+
segment, canvas = coco_segment_info
7689
segments.append(segment)
7790
is_thing[annotation.name] = 0
7891

7992
elif isinstance(annotation.value, (Polygon, Rectangle)):
80-
segment, canvas = vector_to_coco_segment_info(
93+
coco_vector_info = vector_to_coco_segment_info(
8194
canvas,
8295
annotation,
8396
annotation_idx=(class_idx if all_stuff else annotation_idx)
8497
+ 1,
8598
image=image,
8699
category_id=categories[annotation.name])
100+
101+
if coco_segment_info is None:
102+
# Filter out empty annotations
103+
continue
104+
105+
segment, canvas = coco_vector_info
87106
segments.append(segment)
88107
is_thing[annotation.name] = 1 - int(all_stuff)
89108

0 commit comments

Comments
 (0)