Skip to content

Commit 9a3ca4c

Browse files
committed
Ensure shapely coordinate consistency across Python versions
1 parent 50e045f commit 9a3ca4c

File tree

1 file changed

+39
-1
lines changed
  • libs/labelbox/src/labelbox/data/annotation_types/geometry

1 file changed

+39
-1
lines changed

libs/labelbox/src/labelbox/data/annotation_types/geometry/mask.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class Mask(Geometry):
3737

3838
@property
3939
def geometry(self) -> Dict[str, Tuple[int, int, int]]:
40+
# Extract mask contours and build geometry
4041
mask = self.draw(color=1)
4142
contours, hierarchy = cv2.findContours(
4243
image=mask, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE
@@ -62,7 +63,44 @@ def geometry(self) -> Dict[str, Tuple[int, int, int]]:
6263
if not holes.is_valid:
6364
holes = holes.buffer(0)
6465

65-
return external_polygons.difference(holes).__geo_interface__
66+
# Get geometry result
67+
result_geometry = external_polygons.difference(holes)
68+
69+
# Ensure consistent MultiPolygon format across shapely versions
70+
if (
71+
hasattr(result_geometry, "geom_type")
72+
and result_geometry.geom_type == "Polygon"
73+
):
74+
from shapely.geometry import MultiPolygon
75+
76+
result_geometry = MultiPolygon([result_geometry])
77+
78+
geometry_dict = result_geometry.__geo_interface__
79+
return self._normalize_coordinates(geometry_dict)
80+
81+
def _normalize_coordinates(self, geometry_dict):
82+
"""Normalize coordinates to ensure consistent tuple format across shapely versions"""
83+
84+
def ensure_tuple_coords(obj):
85+
"""Recursively ensure coordinate pairs are tuples"""
86+
if isinstance(obj, (list, tuple)):
87+
# Check if this is a coordinate pair [x, y]
88+
if len(obj) == 2 and all(
89+
isinstance(x, (int, float)) for x in obj
90+
):
91+
return (float(obj[0]), float(obj[1]))
92+
else:
93+
# Recursively process nested structures, preserving list/tuple types
94+
if isinstance(obj, list):
95+
return [ensure_tuple_coords(item) for item in obj]
96+
else:
97+
return tuple(ensure_tuple_coords(item) for item in obj)
98+
return obj
99+
100+
result = geometry_dict.copy()
101+
if "coordinates" in result:
102+
result["coordinates"] = ensure_tuple_coords(result["coordinates"])
103+
return result
66104

67105
def draw(
68106
self,

0 commit comments

Comments
 (0)