Skip to content

Commit

Permalink
Use z_order as a class property (cvat-ai#1589)
Browse files Browse the repository at this point in the history
* Use z_order as a class property

* Fix z_order use in voc

* Update changelog
  • Loading branch information
zhiltsov-max authored and Fernando Martínez González committed Aug 3, 2020
1 parent d4dbd53 commit 46a60fd
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 86 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Synchronization with remote git repo (<https://github.com/opencv/cvat/pull/1582>)
- A problem with mask to polygons conversion when polygons are too small (<https://github.com/opencv/cvat/pull/1581>)
- Unable to upload video with uneven size (<https://github.com/opencv/cvat/pull/1594>)
- Fixed an issue with `z_order` having no effect on segmentations (<https://github.com/opencv/cvat/pull/1589>)

### Security
-
Expand Down
14 changes: 9 additions & 5 deletions cvat/apps/dataset_manager/bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,6 @@ def convert_attrs(label, cvat_attrs):
anno_label = map_label(shape_obj.label)
anno_attr = convert_attrs(shape_obj.label, shape_obj.attributes)
anno_attr['occluded'] = shape_obj.occluded
anno_attr['z_order'] = shape_obj.z_order

if hasattr(shape_obj, 'track_id'):
anno_attr['track_id'] = shape_obj.track_id
Expand All @@ -507,17 +506,21 @@ def convert_attrs(label, cvat_attrs):
anno_points = shape_obj.points
if shape_obj.type == ShapeType.POINTS:
anno = datumaro.Points(anno_points,
label=anno_label, attributes=anno_attr, group=anno_group)
label=anno_label, attributes=anno_attr, group=anno_group,
z_order=shape_obj.z_order)
elif shape_obj.type == ShapeType.POLYLINE:
anno = datumaro.PolyLine(anno_points,
label=anno_label, attributes=anno_attr, group=anno_group)
label=anno_label, attributes=anno_attr, group=anno_group,
z_order=shape_obj.z_order)
elif shape_obj.type == ShapeType.POLYGON:
anno = datumaro.Polygon(anno_points,
label=anno_label, attributes=anno_attr, group=anno_group)
label=anno_label, attributes=anno_attr, group=anno_group,
z_order=shape_obj.z_order)
elif shape_obj.type == ShapeType.RECTANGLE:
x0, y0, x1, y1 = anno_points
anno = datumaro.Bbox(x0, y0, x1 - x0, y1 - y0,
label=anno_label, attributes=anno_attr, group=anno_group)
label=anno_label, attributes=anno_attr, group=anno_group,
z_order=shape_obj.z_order)
elif shape_obj.type == ShapeType.CUBOID:
continue # Datumaro does not support cuboids
else:
Expand Down Expand Up @@ -590,6 +593,7 @@ def import_dm_annotations(dm_dataset, task_data):
label=label_cat.items[ann.label].name,
points=ann.points,
occluded=ann.attributes.get('occluded') == True,
z_order=ann.z_order,
group=group_map.get(ann.group, 0),
attributes=[task_data.Attribute(name=n, value=str(v))
for n, v in ann.attributes.items()],
Expand Down
13 changes: 7 additions & 6 deletions datumaro/datumaro/components/extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,21 +270,22 @@ def from_instance_masks(instance_masks,
if instance_ids is not None:
assert len(instance_ids) == len(instance_masks)
else:
instance_ids = range(1, len(instance_masks) + 1)
instance_ids = [None] * len(instance_masks)

if instance_labels is not None:
assert len(instance_labels) == len(instance_masks)
else:
instance_labels = [None] * len(instance_masks)

instance_masks = sorted(instance_masks, key=lambda m: m.z_order)
instance_masks = sorted(
zip(instance_masks, instance_ids, instance_labels),
key=lambda m: m[0].z_order)

instance_mask = [m.as_instance_mask(id) for m, id in
zip(instance_masks, instance_ids)]
instance_mask = [m.as_instance_mask(id if id is not None else 1 + idx)
for idx, (m, id, _) in enumerate(instance_masks)]
instance_mask = merge_masks(instance_mask)

cls_mask = [m.as_class_mask(c) for m, c in
zip(instance_masks, instance_labels)]
cls_mask = [m.as_class_mask(c) for m, _, c in instance_masks]
cls_mask = merge_masks(cls_mask)
return __class__(class_mask=cls_mask, instance_mask=instance_mask)

Expand Down
2 changes: 1 addition & 1 deletion datumaro/datumaro/plugins/cvat_format/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ def _write_shape(self, shape):
)),
]))

shape_data['z_order'] = str(int(shape.attributes.get('z_order', 0)))
shape_data['z_order'] = str(int(shape.z_order))
if shape.group:
shape_data['group_id'] = str(shape.group)

Expand Down
13 changes: 5 additions & 8 deletions datumaro/datumaro/plugins/cvat_format/extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,6 @@ def consumed(expected_state, tag):
"Expected 'meta' section in the annotation file, path: %s" % states

common_attrs = ['occluded']
if has_z_order:
common_attrs.append('z_order')
if mode == 'interpolation':
common_attrs.append('keyframe')
common_attrs.append('outside')
Expand All @@ -260,8 +258,6 @@ def _parse_shape_ann(cls, ann, categories):
attributes = ann.get('attributes', {})
if 'occluded' in categories[AnnotationType.label].attributes:
attributes['occluded'] = ann.get('occluded', False)
if 'z_order' in categories[AnnotationType.label].attributes:
attributes['z_order'] = ann.get('z_order', 0)
if 'outside' in categories[AnnotationType.label].attributes:
attributes['outside'] = ann.get('outside', False)
if 'keyframe' in categories[AnnotationType.label].attributes:
Expand All @@ -272,24 +268,25 @@ def _parse_shape_ann(cls, ann, categories):
label = ann.get('label')
label_id = categories[AnnotationType.label].find(label)[0]

z_order = ann.get('z_order', 0)
points = ann.get('points', [])

if ann_type == 'polyline':
return PolyLine(points, label=label_id,
return PolyLine(points, label=label_id, z_order=z_order,
id=ann_id, attributes=attributes, group=group)

elif ann_type == 'polygon':
return Polygon(points, label=label_id,
return Polygon(points, label=label_id, z_order=z_order,
id=ann_id, attributes=attributes, group=group)

elif ann_type == 'points':
return Points(points, label=label_id,
return Points(points, label=label_id, z_order=z_order,
id=ann_id, attributes=attributes, group=group)

elif ann_type == 'box':
x, y = points[0], points[1]
w, h = points[2] - x, points[3] - y
return Bbox(x, y, w, h, label=label_id,
return Bbox(x, y, w, h, label=label_id, z_order=z_order,
id=ann_id, attributes=attributes, group=group)

else:
Expand Down
33 changes: 14 additions & 19 deletions datumaro/datumaro/plugins/datumaro_format/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from datumaro.components.converter import Converter
from datumaro.components.extractor import (
DEFAULT_SUBSET_NAME, Annotation,
DEFAULT_SUBSET_NAME, Annotation, _Shape,
Label, Mask, RleMask, Points, Polygon, PolyLine, Bbox, Caption,
LabelCategories, MaskCategories, PointsCategories
)
Expand Down Expand Up @@ -131,43 +131,38 @@ def _convert_mask_object(self, obj):
# serialize as compressed COCO mask
'counts': rle['counts'].decode('ascii'),
'size': list(int(c) for c in rle['size']),
}
},
'z_order': obj.z_order,
})
return converted

def _convert_polyline_object(self, obj):
def _convert_shape_object(self, obj):
assert isinstance(obj, _Shape)
converted = self._convert_annotation(obj)

converted.update({
'label_id': cast(obj.label, int),
'points': [float(p) for p in obj.points],
'z_order': obj.z_order,
})
return converted

def _convert_polygon_object(self, obj):
converted = self._convert_annotation(obj)
def _convert_polyline_object(self, obj):
return self._convert_shape_object(obj)

converted.update({
'label_id': cast(obj.label, int),
'points': [float(p) for p in obj.points],
})
return converted
def _convert_polygon_object(self, obj):
return self._convert_shape_object(obj)

def _convert_bbox_object(self, obj):
converted = self._convert_annotation(obj)

converted.update({
'label_id': cast(obj.label, int),
'bbox': [float(p) for p in obj.get_bbox()],
})
converted = self._convert_shape_object(obj)
converted.pop('points', None)
converted['bbox'] = [float(p) for p in obj.get_bbox()]
return converted

def _convert_points_object(self, obj):
converted = self._convert_annotation(obj)
converted = self._convert_shape_object(obj)

converted.update({
'label_id': cast(obj.label, int),
'points': [float(p) for p in obj.points],
'visibility': [int(v.value) for v in obj.visibility],
})
return converted
Expand Down
30 changes: 15 additions & 15 deletions datumaro/datumaro/plugins/datumaro_format/extractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,41 +107,41 @@ def _load_annotations(self, item):
attributes = ann.get('attributes')
group = ann.get('group')

label_id = ann.get('label_id')
z_order = ann.get('z_order')
points = ann.get('points')

if ann_type == AnnotationType.label:
label_id = ann.get('label_id')
loaded.append(Label(label=label_id,
id=ann_id, attributes=attributes, group=group))

elif ann_type == AnnotationType.mask:
label_id = ann.get('label_id')
rle = ann['rle']
rle['counts'] = rle['counts'].encode('ascii')
loaded.append(RleMask(rle=rle, label=label_id,
id=ann_id, attributes=attributes, group=group))
id=ann_id, attributes=attributes, group=group,
z_order=z_order))

elif ann_type == AnnotationType.polyline:
label_id = ann.get('label_id')
points = ann.get('points')
loaded.append(PolyLine(points, label=label_id,
id=ann_id, attributes=attributes, group=group))
id=ann_id, attributes=attributes, group=group,
z_order=z_order))

elif ann_type == AnnotationType.polygon:
label_id = ann.get('label_id')
points = ann.get('points')
loaded.append(Polygon(points, label=label_id,
id=ann_id, attributes=attributes, group=group))
id=ann_id, attributes=attributes, group=group,
z_order=z_order))

elif ann_type == AnnotationType.bbox:
label_id = ann.get('label_id')
x, y, w, h = ann.get('bbox')
x, y, w, h = ann['bbox']
loaded.append(Bbox(x, y, w, h, label=label_id,
id=ann_id, attributes=attributes, group=group))
id=ann_id, attributes=attributes, group=group,
z_order=z_order))

elif ann_type == AnnotationType.points:
label_id = ann.get('label_id')
points = ann.get('points')
loaded.append(Points(points, label=label_id,
id=ann_id, attributes=attributes, group=group))
id=ann_id, attributes=attributes, group=group,
z_order=z_order))

elif ann_type == AnnotationType.caption:
caption = ann.get('caption')
Expand Down
46 changes: 23 additions & 23 deletions datumaro/tests/test_cvat_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,20 @@ def __iter__(self):
return iter([
DatasetItem(id=0, subset='train', image=np.ones((8, 8, 3)),
annotations=[
Bbox(0, 2, 4, 2, label=0,
Bbox(0, 2, 4, 2, label=0, z_order=1,
attributes={
'occluded': True, 'z_order': 1,
'occluded': True,
'a1': True, 'a2': 'v3'
}),
PolyLine([1, 2, 3, 4, 5, 6, 7, 8],
attributes={'occluded': False, 'z_order': 0}),
PolyLine([1, 2, 3, 4, 5, 6, 7, 8], z_order=0,
attributes={'occluded': False}),
]),
DatasetItem(id=1, subset='train', image=np.ones((10, 10, 3)),
annotations=[
Polygon([1, 2, 3, 4, 6, 5],
attributes={'occluded': False, 'z_order': 1}),
Points([1, 2, 3, 4, 5, 6], label=1,
attributes={'occluded': False, 'z_order': 2}),
Polygon([1, 2, 3, 4, 6, 5], z_order=1,
attributes={'occluded': False}),
Points([1, 2, 3, 4, 5, 6], label=1, z_order=2,
attributes={'occluded': False}),
]),
])

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

class SrcExtractor(Extractor):
def __iter__(self):
Expand Down Expand Up @@ -194,9 +194,9 @@ def __iter__(self):

DatasetItem(id=2, subset='s2', image=np.ones((5, 10, 3)),
annotations=[
Polygon([0, 0, 4, 0, 4, 4],
Polygon([0, 0, 4, 0, 4, 4], z_order=1,
label=3, group=4,
attributes={ 'z_order': 1, 'occluded': False }),
attributes={ 'occluded': False }),
PolyLine([5, 0, 9, 0, 5, 5]), # will be skipped as no label
]
),
Expand All @@ -213,36 +213,36 @@ def __iter__(self):
return iter([
DatasetItem(id=0, subset='s1', image=np.zeros((5, 10, 3)),
annotations=[
Polygon([0, 0, 4, 0, 4, 4],
Polygon([0, 0, 4, 0, 4, 4], z_order=0,
label=1, group=4,
attributes={ 'z_order': 0, 'occluded': True }),
Polygon([5, 0, 9, 0, 5, 5],
attributes={ 'occluded': True }),
Polygon([5, 0, 9, 0, 5, 5], z_order=0,
label=2, group=4,
attributes={ 'z_order': 0, 'occluded': False }),
Points([1, 1, 3, 2, 2, 3],
attributes={ 'occluded': False }),
Points([1, 1, 3, 2, 2, 3], z_order=0,
label=2,
attributes={ 'z_order': 0, 'occluded': False,
attributes={ 'occluded': False,
'a1': 'x', 'a2': 42 }),
Label(1),
Label(2, attributes={ 'a1': 'y', 'a2': 44 }),
]
),
DatasetItem(id=1, subset='s1',
annotations=[
PolyLine([0, 0, 4, 0, 4, 4],
PolyLine([0, 0, 4, 0, 4, 4], z_order=0,
label=3, group=4,
attributes={ 'z_order': 0, 'occluded': False }),
Bbox(5, 0, 1, 9,
attributes={ 'occluded': False }),
Bbox(5, 0, 1, 9, z_order=0,
label=3, group=4,
attributes={ 'z_order': 0, 'occluded': False }),
attributes={ 'occluded': False }),
]
),

DatasetItem(id=2, subset='s2', image=np.ones((5, 10, 3)),
annotations=[
Polygon([0, 0, 4, 0, 4, 4],
Polygon([0, 0, 4, 0, 4, 4], z_order=1,
label=3, group=4,
attributes={ 'z_order': 1, 'occluded': False }),
attributes={ 'occluded': False }),
]
),

Expand Down
10 changes: 5 additions & 5 deletions datumaro/tests/test_datumaro_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ def __iter__(self):
'x': 1,
'y': '2',
}),
Bbox(1, 2, 3, 4, label=4, id=4, attributes={
Bbox(1, 2, 3, 4, label=4, id=4, z_order=1, attributes={
'score': 1.0,
}),
Bbox(5, 6, 7, 8, id=5, group=5),
Points([1, 2, 2, 0, 1, 1], label=0, id=5),
Mask(label=3, id=5, image=np.ones((2, 3))),
Points([1, 2, 2, 0, 1, 1], label=0, id=5, z_order=4),
Mask(label=3, id=5, z_order=2, image=np.ones((2, 3))),
]),
DatasetItem(id=21, subset='train',
annotations=[
Expand All @@ -43,8 +43,8 @@ def __iter__(self):

DatasetItem(id=2, subset='val',
annotations=[
PolyLine([1, 2, 3, 4, 5, 6, 7, 8], id=11),
Polygon([1, 2, 3, 4, 5, 6, 7, 8], id=12),
PolyLine([1, 2, 3, 4, 5, 6, 7, 8], id=11, z_order=1),
Polygon([1, 2, 3, 4, 5, 6, 7, 8], id=12, z_order=4),
]),

DatasetItem(id=42, subset='test'),
Expand Down
Loading

0 comments on commit 46a60fd

Please sign in to comment.