@@ -159,12 +159,16 @@ def __eq__(self, other):
159
159
160
160
class MaskObject (Annotation ):
161
161
# pylint: disable=redefined-builtin
162
- def __init__ (self , image = None , label = None ,
162
+ def __init__ (self , image = None , label = None , z_order = None ,
163
163
id = None , attributes = None , group = None ):
164
164
super ().__init__ (id = id , type = AnnotationType .mask ,
165
165
attributes = attributes , group = group )
166
166
self ._image = image
167
167
self ._label = label
168
+
169
+ if z_order is None :
170
+ z_order = 0
171
+ self ._z_order = z_order
168
172
# pylint: enable=redefined-builtin
169
173
170
174
@property
@@ -181,22 +185,69 @@ def painted_data(self, colormap):
181
185
raise NotImplementedError ()
182
186
183
187
def area (self ):
184
- raise NotImplementedError ()
188
+ if self ._label is None :
189
+ raise NotImplementedError ()
190
+ return np .count_nonzero (self .image )
185
191
186
192
def extract (self , class_id ):
187
193
raise NotImplementedError ()
188
194
189
- def bbox (self ):
190
- raise NotImplementedError ()
195
+ def get_bbox (self ):
196
+ if self ._label is None :
197
+ raise NotImplementedError ()
198
+ image = self .image
199
+ cols = np .any (image , axis = 0 )
200
+ rows = np .any (image , axis = 1 )
201
+ x0 , x1 = np .where (cols )[0 ][[0 , - 1 ]]
202
+ y0 , y1 = np .where (rows )[0 ][[0 , - 1 ]]
203
+ return [x0 , y0 , x1 - x0 , y1 - y0 ]
204
+
205
+ @property
206
+ def z_order (self ):
207
+ return self ._z_order
191
208
192
209
def __eq__ (self , other ):
193
210
if not super ().__eq__ (other ):
194
211
return False
195
212
return \
196
213
(self .label == other .label ) and \
214
+ (self .z_order == other .z_order ) and \
197
215
(self .image is not None and other .image is not None and \
198
216
np .all (self .image == other .image ))
199
217
218
+ class RleMask (MaskObject ):
219
+ # pylint: disable=redefined-builtin
220
+ def __init__ (self , rle = None , label = None , z_order = None ,
221
+ id = None , attributes = None , group = None ):
222
+ lazy_decode = self ._lazy_decode (rle )
223
+ super ().__init__ (image = lazy_decode , label = label , z_order = z_order ,
224
+ id = id , attributes = attributes , group = group )
225
+
226
+ self ._rle = rle
227
+ # pylint: enable=redefined-builtin
228
+
229
+ @staticmethod
230
+ def _lazy_decode (rle ):
231
+ from pycocotools import mask as mask_utils
232
+ return lambda : mask_utils .decode (rle ).astype (np .bool )
233
+
234
+ def area (self ):
235
+ from pycocotools import mask as mask_utils
236
+ return mask_utils .area (self ._rle )
237
+
238
+ def bbox (self ):
239
+ from pycocotools import mask as mask_utils
240
+ return mask_utils .toBbox (self ._rle )
241
+
242
+ @property
243
+ def rle (self ):
244
+ return self ._rle
245
+
246
+ def __eq__ (self , other ):
247
+ if not isinstance (other , __class__ ):
248
+ return super ().__eq__ (other )
249
+ return self ._rle == other ._rle
250
+
200
251
def compute_iou (bbox_a , bbox_b ):
201
252
aX , aY , aW , aH = bbox_a
202
253
bX , bY , bW , bH = bbox_b
@@ -217,12 +268,16 @@ def compute_iou(bbox_a, bbox_b):
217
268
218
269
class ShapeObject (Annotation ):
219
270
# pylint: disable=redefined-builtin
220
- def __init__ (self , type , points = None , label = None ,
271
+ def __init__ (self , type , points = None , label = None , z_order = None ,
221
272
id = None , attributes = None , group = None ):
222
273
super ().__init__ (id = id , type = type ,
223
274
attributes = attributes , group = group )
224
275
self .points = points
225
276
self .label = label
277
+
278
+ if z_order is None :
279
+ z_order = 0
280
+ self ._z_order = z_order
226
281
# pylint: enable=redefined-builtin
227
282
228
283
def area (self ):
@@ -247,22 +302,24 @@ def get_bbox(self):
247
302
def get_points (self ):
248
303
return self .points
249
304
250
- def get_mask (self ):
251
- raise NotImplementedError ()
305
+ @property
306
+ def z_order (self ):
307
+ return self ._z_order
252
308
253
309
def __eq__ (self , other ):
254
310
if not super ().__eq__ (other ):
255
311
return False
256
312
return \
257
313
(self .points == other .points ) and \
314
+ (self .z_order == other .z_order ) and \
258
315
(self .label == other .label )
259
316
260
317
class PolyLineObject (ShapeObject ):
261
318
# pylint: disable=redefined-builtin
262
- def __init__ (self , points = None ,
263
- label = None , id = None , attributes = None , group = None ):
319
+ def __init__ (self , points = None , label = None , z_order = None ,
320
+ id = None , attributes = None , group = None ):
264
321
super ().__init__ (type = AnnotationType .polyline ,
265
- points = points , label = label ,
322
+ points = points , label = label , z_order = z_order ,
266
323
id = id , attributes = attributes , group = group )
267
324
# pylint: enable=redefined-builtin
268
325
@@ -274,12 +331,12 @@ def area(self):
274
331
275
332
class PolygonObject (ShapeObject ):
276
333
# pylint: disable=redefined-builtin
277
- def __init__ (self , points = None ,
334
+ def __init__ (self , points = None , z_order = None ,
278
335
label = None , id = None , attributes = None , group = None ):
279
336
if points is not None :
280
337
assert len (points ) % 2 == 0 and 3 <= len (points ) // 2 , "Wrong polygon points: %s" % points
281
338
super ().__init__ (type = AnnotationType .polygon ,
282
- points = points , label = label ,
339
+ points = points , label = label , z_order = z_order ,
283
340
id = id , attributes = attributes , group = group )
284
341
# pylint: enable=redefined-builtin
285
342
@@ -291,15 +348,15 @@ def area(self):
291
348
292
349
_ , _ , w , h = self .get_bbox ()
293
350
rle = mask_utils .frPyObjects ([self .get_points ()], h , w )
294
- area = mask_utils .area (rle )
351
+ area = mask_utils .area (rle )[ 0 ]
295
352
return area
296
353
297
354
class BboxObject (ShapeObject ):
298
355
# pylint: disable=redefined-builtin
299
- def __init__ (self , x = 0 , y = 0 , w = 0 , h = 0 ,
300
- label = None , id = None , attributes = None , group = None ):
356
+ def __init__ (self , x = 0 , y = 0 , w = 0 , h = 0 , label = None , z_order = None ,
357
+ id = None , attributes = None , group = None ):
301
358
super ().__init__ (type = AnnotationType .bbox ,
302
- points = [x , y , x + w , y + h ], label = label ,
359
+ points = [x , y , x + w , y + h ], label = label , z_order = z_order ,
303
360
id = id , attributes = attributes , group = group )
304
361
# pylint: enable=redefined-builtin
305
362
@@ -368,7 +425,7 @@ class PointsObject(ShapeObject):
368
425
])
369
426
370
427
# pylint: disable=redefined-builtin
371
- def __init__ (self , points = None , visibility = None , label = None ,
428
+ def __init__ (self , points = None , visibility = None , label = None , z_order = None ,
372
429
id = None , attributes = None , group = None ):
373
430
if points is not None :
374
431
assert len (points ) % 2 == 0
@@ -381,10 +438,10 @@ def __init__(self, points=None, visibility=None, label=None,
381
438
else :
382
439
visibility = []
383
440
for _ in range (len (points ) // 2 ):
384
- visibility .append (self .Visibility .absent )
441
+ visibility .append (self .Visibility .visible )
385
442
386
443
super ().__init__ (type = AnnotationType .points ,
387
- points = points , label = label ,
444
+ points = points , label = label , z_order = z_order ,
388
445
id = id , attributes = attributes , group = group )
389
446
390
447
self .visibility = visibility
@@ -393,6 +450,17 @@ def __init__(self, points=None, visibility=None, label=None,
393
450
def area (self ):
394
451
return 0
395
452
453
+ def get_bbox (self ):
454
+ xs = [p for p , v in zip (self .points [0 ::2 ], self .visibility )
455
+ if v != __class__ .Visibility .absent ]
456
+ ys = [p for p , v in zip (self .points [1 ::2 ], self .visibility )
457
+ if v != __class__ .Visibility .absent ]
458
+ x0 = min (xs , default = 0 )
459
+ x1 = max (xs , default = 0 )
460
+ y0 = min (ys , default = 0 )
461
+ y1 = max (ys , default = 0 )
462
+ return [x0 , y0 , x1 - x0 , y1 - y0 ]
463
+
396
464
def __eq__ (self , other ):
397
465
if not super ().__eq__ (other ):
398
466
return False
0 commit comments