@@ -64,6 +64,80 @@ def geometry(self) -> Dict[str, Tuple[int, int, int]]:
64
64
65
65
return external_polygons .difference (holes ).__geo_interface__
66
66
67
+ def _extract_polygons_from_contours (self , contours : List ) -> MultiPolygon :
68
+ contours = map (np .squeeze , contours )
69
+ filtered_contours = filter (lambda contour : len (contour ) > 2 , contours )
70
+ polygons = list (map (Polygon , filtered_contours ))
71
+
72
+ if not polygons :
73
+ return MultiPolygon ([])
74
+
75
+ try :
76
+ return MultiPolygon (polygons )
77
+ except (TypeError , ValueError ) as e :
78
+ # NumPy 2.0 compatibility - simple wrapper for required operations
79
+ if "create_collection" in str (e ) or "casting rule" in str (e ):
80
+
81
+ class SimpleWrapper :
82
+ def __init__ (self , polygons ):
83
+ self .is_valid = True
84
+ self ._polygons = polygons
85
+
86
+ def buffer (self , distance ):
87
+ buffered = [p .buffer (distance ) for p in self ._polygons ]
88
+ return SimpleWrapper (buffered )
89
+
90
+ def difference (self , other ):
91
+ if (
92
+ hasattr (other , "_polygons" )
93
+ and self ._polygons
94
+ and other ._polygons
95
+ ):
96
+ from shapely .ops import unary_union
97
+
98
+ self_geom = (
99
+ unary_union (self ._polygons )
100
+ if len (self ._polygons ) > 1
101
+ else self ._polygons [0 ]
102
+ )
103
+ other_geom = (
104
+ unary_union (other ._polygons )
105
+ if len (other ._polygons ) > 1
106
+ else other ._polygons [0 ]
107
+ )
108
+ result = self_geom .difference (other_geom )
109
+ result_polygons = (
110
+ list (result .geoms )
111
+ if hasattr (result , "geoms" )
112
+ else [result ]
113
+ )
114
+ return SimpleWrapper (result_polygons )
115
+ return self
116
+
117
+ @property
118
+ def __geo_interface__ (self ):
119
+ if len (self ._polygons ) == 1 :
120
+ poly_coords = self ._polygons [0 ].__geo_interface__ [
121
+ "coordinates"
122
+ ]
123
+ return {
124
+ "type" : "MultiPolygon" ,
125
+ "coordinates" : [poly_coords ],
126
+ }
127
+ else :
128
+ all_coords = [
129
+ p .__geo_interface__ ["coordinates" ]
130
+ for p in self ._polygons
131
+ ]
132
+ return {
133
+ "type" : "MultiPolygon" ,
134
+ "coordinates" : all_coords ,
135
+ }
136
+
137
+ return SimpleWrapper (polygons )
138
+ else :
139
+ raise
140
+
67
141
def draw (
68
142
self ,
69
143
height : Optional [int ] = None ,
@@ -109,12 +183,6 @@ def draw(
109
183
canvas [mask .astype (bool )] = color
110
184
return canvas
111
185
112
- def _extract_polygons_from_contours (self , contours : List ) -> MultiPolygon :
113
- contours = map (np .squeeze , contours )
114
- filtered_contours = filter (lambda contour : len (contour ) > 2 , contours )
115
- polygons = map (Polygon , filtered_contours )
116
- return MultiPolygon (polygons )
117
-
118
186
def create_url (self , signer : Callable [[bytes ], str ]) -> str :
119
187
"""
120
188
Update the segmentation mask to have a url.
0 commit comments