Skip to content

Commit 4340896

Browse files
author
Matt Sokoloff
committed
fix invalid polygons
1 parent ec8f95e commit 4340896

File tree

3 files changed

+36
-10
lines changed

3 files changed

+36
-10
lines changed

labelbox/data/annotation_types/geometry/mask.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@ class Mask(Geometry):
3838
@property
3939
def geometry(self) -> Dict[str, Tuple[int, int, int]]:
4040
mask = self.draw(color=1)
41-
contours, hierarchy = cv2.findContours(image=mask,
42-
mode=cv2.RETR_TREE,
43-
method=cv2.CHAIN_APPROX_NONE)
41+
contours, hierarchy = cv2.findContours(image=mask,mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)
4442

4543
holes = []
4644
external_contours = []
@@ -51,9 +49,16 @@ def geometry(self) -> Dict[str, Tuple[int, int, int]]:
5149
else:
5250
external_contours.append(contours[i])
5351

54-
external_polygons = self._extract_polygons_from_contours(
55-
external_contours)
52+
external_polygons = self._extract_polygons_from_contours(external_contours)
5653
holes = self._extract_polygons_from_contours(holes)
54+
55+
56+
if not external_polygons.is_valid:
57+
external_polygons = external_polygons.buffer(0)
58+
59+
if not holes.is_valid:
60+
holes = holes.buffer(0)
61+
5762
return external_polygons.difference(holes).__geo_interface__
5863

5964
def draw(self,
@@ -78,7 +83,6 @@ def draw(self,
7883
np.ndarray representing only this object
7984
as opposed to the mask that this object references which might have multiple objects determined by colors
8085
"""
81-
8286
mask = self.mask.value
8387
mask = np.alltrue(mask == self.color, axis=2).astype(np.uint8)
8488

labelbox/data/serialization/coco/instance_dataset.py

Lines changed: 2 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

@@ -42,6 +41,8 @@ def mask_to_coco_object_annotation(
4241
iscrowd=0)
4342

4443

44+
45+
4546
def vector_to_coco_object_annotation(annotation: ObjectAnnotation,
4647
annot_idx: int, image_id: int,
4748
category_id: int) -> COCOObjectAnnotation:

labelbox/data/serialization/coco/panoptic_dataset.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,17 @@
1818
from .annotation import PanopticAnnotation, SegmentInfo, get_annotation_lookup
1919

2020

21+
22+
2123
def vector_to_coco_segment_info(canvas: np.ndarray,
2224
annotation: ObjectAnnotation,
2325
annotation_idx: int, image: CocoImage,
2426
category_id: int):
27+
2528
shapely = annotation.value.shapely
29+
if shapely.is_empty:
30+
return
31+
2632
xmin, ymin, xmax, ymax = shapely.bounds
2733
canvas = annotation.value.draw(height=image.height,
2834
width=image.width,
@@ -40,6 +46,9 @@ def mask_to_coco_segment_info(canvas: np.ndarray, annotation,
4046
color = id_to_rgb(annotation_idx)
4147
mask = annotation.value.draw(color=color)
4248
shapely = annotation.value.shapely
49+
if shapely.is_empty:
50+
return
51+
4352
xmin, ymin, xmax, ymax = shapely.bounds
4453
canvas = np.where(canvas == (0, 0, 0), mask, canvas)
4554
return SegmentInfo(id=annotation_idx,
@@ -70,20 +79,32 @@ def process_label(label: Label,
7079
for annotation_idx, annotation in enumerate(annotations[class_name]):
7180
categories[annotation.name] = hash_category_name(annotation.name)
7281
if isinstance(annotation.value, Mask):
73-
segment, canvas = (mask_to_coco_segment_info(
82+
coco_segment_info = mask_to_coco_segment_info(
7483
canvas, annotation, class_idx + 1,
75-
categories[annotation.name]))
84+
categories[annotation.name])
85+
86+
if coco_segment_info is None:
87+
# Filter out empty masks
88+
continue
89+
90+
segment, canvas = coco_segment_info
7691
segments.append(segment)
7792
is_thing[annotation.name] = 0
7893

7994
elif isinstance(annotation.value, (Polygon, Rectangle)):
80-
segment, canvas = vector_to_coco_segment_info(
95+
coco_vector_info = vector_to_coco_segment_info(
8196
canvas,
8297
annotation,
8398
annotation_idx=(class_idx if all_stuff else annotation_idx)
8499
+ 1,
85100
image=image,
86101
category_id=categories[annotation.name])
102+
103+
if coco_segment_info is None:
104+
# Filter out empty annotations
105+
continue
106+
107+
segment, canvas = coco_vector_info
87108
segments.append(segment)
88109
is_thing[annotation.name] = 1 - int(all_stuff)
89110

0 commit comments

Comments
 (0)