Skip to content

Commit 5931bab

Browse files
committed
Add coordinate format normalization
1 parent 50e045f commit 5931bab

File tree

1 file changed

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

1 file changed

+36
-1
lines changed

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

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,40 @@ class Mask(Geometry):
3535
mask: MaskData
3636
color: Union[Tuple[int, int, int], int]
3737

38+
def _normalize_coordinates(self, geometry_dict: Dict) -> Dict:
39+
"""
40+
Normalize coordinate format to lists for backward compatibility.
41+
42+
Shapely versions 2.0.3 and earlier return coordinates as lists,
43+
while 2.0.6+ return tuples. This ensures consistent list format
44+
regardless of shapely version.
45+
46+
Args:
47+
geometry_dict: GeoJSON-style geometry dictionary
48+
49+
Returns:
50+
Geometry dictionary with coordinates normalized to list format
51+
"""
52+
def normalize_coord_sequence(coords):
53+
"""Recursively normalize coordinate sequences"""
54+
if isinstance(coords, (list, tuple)):
55+
if len(coords) == 2 and isinstance(coords[0], (int, float)):
56+
# This is a coordinate pair [x, y] or (x, y)
57+
return [float(coords[0]), float(coords[1])]
58+
else:
59+
# This is a sequence of coordinates or nested sequences
60+
return [normalize_coord_sequence(item) for item in coords]
61+
return coords
62+
63+
if 'coordinates' in geometry_dict:
64+
geometry_dict = geometry_dict.copy()
65+
geometry_dict['coordinates'] = normalize_coord_sequence(geometry_dict['coordinates'])
66+
67+
return geometry_dict
68+
3869
@property
3970
def geometry(self) -> Dict[str, Tuple[int, int, int]]:
71+
# Extract mask contours and build geometry
4072
mask = self.draw(color=1)
4173
contours, hierarchy = cv2.findContours(
4274
image=mask, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE
@@ -62,7 +94,10 @@ def geometry(self) -> Dict[str, Tuple[int, int, int]]:
6294
if not holes.is_valid:
6395
holes = holes.buffer(0)
6496

65-
return external_polygons.difference(holes).__geo_interface__
97+
# Get geometry from shapely and normalize coordinates for consistency
98+
# This ensures customers always get list format regardless of shapely version
99+
geometry_dict = external_polygons.difference(holes).__geo_interface__
100+
return self._normalize_coordinates(geometry_dict)
66101

67102
def draw(
68103
self,

0 commit comments

Comments
 (0)