Skip to content

Commit e2dedb2

Browse files
authored
Use z_order as a class property (#1589)
* Use z_order as a class property * Fix z_order use in voc * Update changelog
1 parent 485bc8d commit e2dedb2

File tree

10 files changed

+84
-86
lines changed

10 files changed

+84
-86
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5656
- Synchronization with remote git repo (<https://github.com/opencv/cvat/pull/1582>)
5757
- A problem with mask to polygons conversion when polygons are too small (<https://github.com/opencv/cvat/pull/1581>)
5858
- Unable to upload video with uneven size (<https://github.com/opencv/cvat/pull/1594>)
59+
- Fixed an issue with `z_order` having no effect on segmentations (<https://github.com/opencv/cvat/pull/1589>)
5960

6061
### Security
6162
-

cvat/apps/dataset_manager/bindings.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,6 @@ def convert_attrs(label, cvat_attrs):
498498
anno_label = map_label(shape_obj.label)
499499
anno_attr = convert_attrs(shape_obj.label, shape_obj.attributes)
500500
anno_attr['occluded'] = shape_obj.occluded
501-
anno_attr['z_order'] = shape_obj.z_order
502501

503502
if hasattr(shape_obj, 'track_id'):
504503
anno_attr['track_id'] = shape_obj.track_id
@@ -507,17 +506,21 @@ def convert_attrs(label, cvat_attrs):
507506
anno_points = shape_obj.points
508507
if shape_obj.type == ShapeType.POINTS:
509508
anno = datumaro.Points(anno_points,
510-
label=anno_label, attributes=anno_attr, group=anno_group)
509+
label=anno_label, attributes=anno_attr, group=anno_group,
510+
z_order=shape_obj.z_order)
511511
elif shape_obj.type == ShapeType.POLYLINE:
512512
anno = datumaro.PolyLine(anno_points,
513-
label=anno_label, attributes=anno_attr, group=anno_group)
513+
label=anno_label, attributes=anno_attr, group=anno_group,
514+
z_order=shape_obj.z_order)
514515
elif shape_obj.type == ShapeType.POLYGON:
515516
anno = datumaro.Polygon(anno_points,
516-
label=anno_label, attributes=anno_attr, group=anno_group)
517+
label=anno_label, attributes=anno_attr, group=anno_group,
518+
z_order=shape_obj.z_order)
517519
elif shape_obj.type == ShapeType.RECTANGLE:
518520
x0, y0, x1, y1 = anno_points
519521
anno = datumaro.Bbox(x0, y0, x1 - x0, y1 - y0,
520-
label=anno_label, attributes=anno_attr, group=anno_group)
522+
label=anno_label, attributes=anno_attr, group=anno_group,
523+
z_order=shape_obj.z_order)
521524
elif shape_obj.type == ShapeType.CUBOID:
522525
continue # Datumaro does not support cuboids
523526
else:
@@ -590,6 +593,7 @@ def import_dm_annotations(dm_dataset, task_data):
590593
label=label_cat.items[ann.label].name,
591594
points=ann.points,
592595
occluded=ann.attributes.get('occluded') == True,
596+
z_order=ann.z_order,
593597
group=group_map.get(ann.group, 0),
594598
attributes=[task_data.Attribute(name=n, value=str(v))
595599
for n, v in ann.attributes.items()],

datumaro/datumaro/components/extractor.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -270,21 +270,22 @@ def from_instance_masks(instance_masks,
270270
if instance_ids is not None:
271271
assert len(instance_ids) == len(instance_masks)
272272
else:
273-
instance_ids = range(1, len(instance_masks) + 1)
273+
instance_ids = [None] * len(instance_masks)
274274

275275
if instance_labels is not None:
276276
assert len(instance_labels) == len(instance_masks)
277277
else:
278278
instance_labels = [None] * len(instance_masks)
279279

280-
instance_masks = sorted(instance_masks, key=lambda m: m.z_order)
280+
instance_masks = sorted(
281+
zip(instance_masks, instance_ids, instance_labels),
282+
key=lambda m: m[0].z_order)
281283

282-
instance_mask = [m.as_instance_mask(id) for m, id in
283-
zip(instance_masks, instance_ids)]
284+
instance_mask = [m.as_instance_mask(id if id is not None else 1 + idx)
285+
for idx, (m, id, _) in enumerate(instance_masks)]
284286
instance_mask = merge_masks(instance_mask)
285287

286-
cls_mask = [m.as_class_mask(c) for m, c in
287-
zip(instance_masks, instance_labels)]
288+
cls_mask = [m.as_class_mask(c) for m, _, c in instance_masks]
288289
cls_mask = merge_masks(cls_mask)
289290
return __class__(class_mask=cls_mask, instance_mask=instance_mask)
290291

datumaro/datumaro/plugins/cvat_format/converter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ def _write_shape(self, shape):
271271
)),
272272
]))
273273

274-
shape_data['z_order'] = str(int(shape.attributes.get('z_order', 0)))
274+
shape_data['z_order'] = str(int(shape.z_order))
275275
if shape.group:
276276
shape_data['group_id'] = str(shape.group)
277277

datumaro/datumaro/plugins/cvat_format/extractor.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,6 @@ def consumed(expected_state, tag):
238238
"Expected 'meta' section in the annotation file, path: %s" % states
239239

240240
common_attrs = ['occluded']
241-
if has_z_order:
242-
common_attrs.append('z_order')
243241
if mode == 'interpolation':
244242
common_attrs.append('keyframe')
245243
common_attrs.append('outside')
@@ -260,8 +258,6 @@ def _parse_shape_ann(cls, ann, categories):
260258
attributes = ann.get('attributes', {})
261259
if 'occluded' in categories[AnnotationType.label].attributes:
262260
attributes['occluded'] = ann.get('occluded', False)
263-
if 'z_order' in categories[AnnotationType.label].attributes:
264-
attributes['z_order'] = ann.get('z_order', 0)
265261
if 'outside' in categories[AnnotationType.label].attributes:
266262
attributes['outside'] = ann.get('outside', False)
267263
if 'keyframe' in categories[AnnotationType.label].attributes:
@@ -272,24 +268,25 @@ def _parse_shape_ann(cls, ann, categories):
272268
label = ann.get('label')
273269
label_id = categories[AnnotationType.label].find(label)[0]
274270

271+
z_order = ann.get('z_order', 0)
275272
points = ann.get('points', [])
276273

277274
if ann_type == 'polyline':
278-
return PolyLine(points, label=label_id,
275+
return PolyLine(points, label=label_id, z_order=z_order,
279276
id=ann_id, attributes=attributes, group=group)
280277

281278
elif ann_type == 'polygon':
282-
return Polygon(points, label=label_id,
279+
return Polygon(points, label=label_id, z_order=z_order,
283280
id=ann_id, attributes=attributes, group=group)
284281

285282
elif ann_type == 'points':
286-
return Points(points, label=label_id,
283+
return Points(points, label=label_id, z_order=z_order,
287284
id=ann_id, attributes=attributes, group=group)
288285

289286
elif ann_type == 'box':
290287
x, y = points[0], points[1]
291288
w, h = points[2] - x, points[3] - y
292-
return Bbox(x, y, w, h, label=label_id,
289+
return Bbox(x, y, w, h, label=label_id, z_order=z_order,
293290
id=ann_id, attributes=attributes, group=group)
294291

295292
else:

datumaro/datumaro/plugins/datumaro_format/converter.py

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
from datumaro.components.converter import Converter
1414
from datumaro.components.extractor import (
15-
DEFAULT_SUBSET_NAME, Annotation,
15+
DEFAULT_SUBSET_NAME, Annotation, _Shape,
1616
Label, Mask, RleMask, Points, Polygon, PolyLine, Bbox, Caption,
1717
LabelCategories, MaskCategories, PointsCategories
1818
)
@@ -131,43 +131,38 @@ def _convert_mask_object(self, obj):
131131
# serialize as compressed COCO mask
132132
'counts': rle['counts'].decode('ascii'),
133133
'size': list(int(c) for c in rle['size']),
134-
}
134+
},
135+
'z_order': obj.z_order,
135136
})
136137
return converted
137138

138-
def _convert_polyline_object(self, obj):
139+
def _convert_shape_object(self, obj):
140+
assert isinstance(obj, _Shape)
139141
converted = self._convert_annotation(obj)
140142

141143
converted.update({
142144
'label_id': cast(obj.label, int),
143145
'points': [float(p) for p in obj.points],
146+
'z_order': obj.z_order,
144147
})
145148
return converted
146149

147-
def _convert_polygon_object(self, obj):
148-
converted = self._convert_annotation(obj)
150+
def _convert_polyline_object(self, obj):
151+
return self._convert_shape_object(obj)
149152

150-
converted.update({
151-
'label_id': cast(obj.label, int),
152-
'points': [float(p) for p in obj.points],
153-
})
154-
return converted
153+
def _convert_polygon_object(self, obj):
154+
return self._convert_shape_object(obj)
155155

156156
def _convert_bbox_object(self, obj):
157-
converted = self._convert_annotation(obj)
158-
159-
converted.update({
160-
'label_id': cast(obj.label, int),
161-
'bbox': [float(p) for p in obj.get_bbox()],
162-
})
157+
converted = self._convert_shape_object(obj)
158+
converted.pop('points', None)
159+
converted['bbox'] = [float(p) for p in obj.get_bbox()]
163160
return converted
164161

165162
def _convert_points_object(self, obj):
166-
converted = self._convert_annotation(obj)
163+
converted = self._convert_shape_object(obj)
167164

168165
converted.update({
169-
'label_id': cast(obj.label, int),
170-
'points': [float(p) for p in obj.points],
171166
'visibility': [int(v.value) for v in obj.visibility],
172167
})
173168
return converted

datumaro/datumaro/plugins/datumaro_format/extractor.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -107,41 +107,41 @@ def _load_annotations(self, item):
107107
attributes = ann.get('attributes')
108108
group = ann.get('group')
109109

110+
label_id = ann.get('label_id')
111+
z_order = ann.get('z_order')
112+
points = ann.get('points')
113+
110114
if ann_type == AnnotationType.label:
111-
label_id = ann.get('label_id')
112115
loaded.append(Label(label=label_id,
113116
id=ann_id, attributes=attributes, group=group))
114117

115118
elif ann_type == AnnotationType.mask:
116-
label_id = ann.get('label_id')
117119
rle = ann['rle']
118120
rle['counts'] = rle['counts'].encode('ascii')
119121
loaded.append(RleMask(rle=rle, label=label_id,
120-
id=ann_id, attributes=attributes, group=group))
122+
id=ann_id, attributes=attributes, group=group,
123+
z_order=z_order))
121124

122125
elif ann_type == AnnotationType.polyline:
123-
label_id = ann.get('label_id')
124-
points = ann.get('points')
125126
loaded.append(PolyLine(points, label=label_id,
126-
id=ann_id, attributes=attributes, group=group))
127+
id=ann_id, attributes=attributes, group=group,
128+
z_order=z_order))
127129

128130
elif ann_type == AnnotationType.polygon:
129-
label_id = ann.get('label_id')
130-
points = ann.get('points')
131131
loaded.append(Polygon(points, label=label_id,
132-
id=ann_id, attributes=attributes, group=group))
132+
id=ann_id, attributes=attributes, group=group,
133+
z_order=z_order))
133134

134135
elif ann_type == AnnotationType.bbox:
135-
label_id = ann.get('label_id')
136-
x, y, w, h = ann.get('bbox')
136+
x, y, w, h = ann['bbox']
137137
loaded.append(Bbox(x, y, w, h, label=label_id,
138-
id=ann_id, attributes=attributes, group=group))
138+
id=ann_id, attributes=attributes, group=group,
139+
z_order=z_order))
139140

140141
elif ann_type == AnnotationType.points:
141-
label_id = ann.get('label_id')
142-
points = ann.get('points')
143142
loaded.append(Points(points, label=label_id,
144-
id=ann_id, attributes=attributes, group=group))
143+
id=ann_id, attributes=attributes, group=group,
144+
z_order=z_order))
145145

146146
elif ann_type == AnnotationType.caption:
147147
caption = ann.get('caption')

datumaro/tests/test_cvat_format.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -110,20 +110,20 @@ def __iter__(self):
110110
return iter([
111111
DatasetItem(id=0, subset='train', image=np.ones((8, 8, 3)),
112112
annotations=[
113-
Bbox(0, 2, 4, 2, label=0,
113+
Bbox(0, 2, 4, 2, label=0, z_order=1,
114114
attributes={
115-
'occluded': True, 'z_order': 1,
115+
'occluded': True,
116116
'a1': True, 'a2': 'v3'
117117
}),
118-
PolyLine([1, 2, 3, 4, 5, 6, 7, 8],
119-
attributes={'occluded': False, 'z_order': 0}),
118+
PolyLine([1, 2, 3, 4, 5, 6, 7, 8], z_order=0,
119+
attributes={'occluded': False}),
120120
]),
121121
DatasetItem(id=1, subset='train', image=np.ones((10, 10, 3)),
122122
annotations=[
123-
Polygon([1, 2, 3, 4, 6, 5],
124-
attributes={'occluded': False, 'z_order': 1}),
125-
Points([1, 2, 3, 4, 5, 6], label=1,
126-
attributes={'occluded': False, 'z_order': 2}),
123+
Polygon([1, 2, 3, 4, 6, 5], z_order=1,
124+
attributes={'occluded': False}),
125+
Points([1, 2, 3, 4, 5, 6], label=1, z_order=2,
126+
attributes={'occluded': False}),
127127
]),
128128
])
129129

@@ -163,7 +163,7 @@ def test_can_save_and_load(self):
163163
for i in range(10):
164164
label_categories.add(str(i))
165165
label_categories.items[2].attributes.update(['a1', 'a2'])
166-
label_categories.attributes.update(['z_order', 'occluded'])
166+
label_categories.attributes.update(['occluded'])
167167

168168
class SrcExtractor(Extractor):
169169
def __iter__(self):
@@ -194,9 +194,9 @@ def __iter__(self):
194194

195195
DatasetItem(id=2, subset='s2', image=np.ones((5, 10, 3)),
196196
annotations=[
197-
Polygon([0, 0, 4, 0, 4, 4],
197+
Polygon([0, 0, 4, 0, 4, 4], z_order=1,
198198
label=3, group=4,
199-
attributes={ 'z_order': 1, 'occluded': False }),
199+
attributes={ 'occluded': False }),
200200
PolyLine([5, 0, 9, 0, 5, 5]), # will be skipped as no label
201201
]
202202
),
@@ -213,36 +213,36 @@ def __iter__(self):
213213
return iter([
214214
DatasetItem(id=0, subset='s1', image=np.zeros((5, 10, 3)),
215215
annotations=[
216-
Polygon([0, 0, 4, 0, 4, 4],
216+
Polygon([0, 0, 4, 0, 4, 4], z_order=0,
217217
label=1, group=4,
218-
attributes={ 'z_order': 0, 'occluded': True }),
219-
Polygon([5, 0, 9, 0, 5, 5],
218+
attributes={ 'occluded': True }),
219+
Polygon([5, 0, 9, 0, 5, 5], z_order=0,
220220
label=2, group=4,
221-
attributes={ 'z_order': 0, 'occluded': False }),
222-
Points([1, 1, 3, 2, 2, 3],
221+
attributes={ 'occluded': False }),
222+
Points([1, 1, 3, 2, 2, 3], z_order=0,
223223
label=2,
224-
attributes={ 'z_order': 0, 'occluded': False,
224+
attributes={ 'occluded': False,
225225
'a1': 'x', 'a2': 42 }),
226226
Label(1),
227227
Label(2, attributes={ 'a1': 'y', 'a2': 44 }),
228228
]
229229
),
230230
DatasetItem(id=1, subset='s1',
231231
annotations=[
232-
PolyLine([0, 0, 4, 0, 4, 4],
232+
PolyLine([0, 0, 4, 0, 4, 4], z_order=0,
233233
label=3, group=4,
234-
attributes={ 'z_order': 0, 'occluded': False }),
235-
Bbox(5, 0, 1, 9,
234+
attributes={ 'occluded': False }),
235+
Bbox(5, 0, 1, 9, z_order=0,
236236
label=3, group=4,
237-
attributes={ 'z_order': 0, 'occluded': False }),
237+
attributes={ 'occluded': False }),
238238
]
239239
),
240240

241241
DatasetItem(id=2, subset='s2', image=np.ones((5, 10, 3)),
242242
annotations=[
243-
Polygon([0, 0, 4, 0, 4, 4],
243+
Polygon([0, 0, 4, 0, 4, 4], z_order=1,
244244
label=3, group=4,
245-
attributes={ 'z_order': 1, 'occluded': False }),
245+
attributes={ 'occluded': False }),
246246
]
247247
),
248248

datumaro/tests/test_datumaro_format.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ def __iter__(self):
2727
'x': 1,
2828
'y': '2',
2929
}),
30-
Bbox(1, 2, 3, 4, label=4, id=4, attributes={
30+
Bbox(1, 2, 3, 4, label=4, id=4, z_order=1, attributes={
3131
'score': 1.0,
3232
}),
3333
Bbox(5, 6, 7, 8, id=5, group=5),
34-
Points([1, 2, 2, 0, 1, 1], label=0, id=5),
35-
Mask(label=3, id=5, image=np.ones((2, 3))),
34+
Points([1, 2, 2, 0, 1, 1], label=0, id=5, z_order=4),
35+
Mask(label=3, id=5, z_order=2, image=np.ones((2, 3))),
3636
]),
3737
DatasetItem(id=21, subset='train',
3838
annotations=[
@@ -43,8 +43,8 @@ def __iter__(self):
4343

4444
DatasetItem(id=2, subset='val',
4545
annotations=[
46-
PolyLine([1, 2, 3, 4, 5, 6, 7, 8], id=11),
47-
Polygon([1, 2, 3, 4, 5, 6, 7, 8], id=12),
46+
PolyLine([1, 2, 3, 4, 5, 6, 7, 8], id=11, z_order=1),
47+
Polygon([1, 2, 3, 4, 5, 6, 7, 8], id=12, z_order=4),
4848
]),
4949

5050
DatasetItem(id=42, subset='test'),

0 commit comments

Comments
 (0)