[Datumaro] Change alignment in mask parsing (#1547)

main
zhiltsov-max 6 years ago committed by GitHub
parent 42990906b9
commit 98a9718e63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Task/Job buttons has no "Open in new tab" option (<https://github.com/opencv/cvat/pull/1419>) - Task/Job buttons has no "Open in new tab" option (<https://github.com/opencv/cvat/pull/1419>)
- Delete point context menu option has no shortcut hint (<https://github.com/opencv/cvat/pull/1416>) - Delete point context menu option has no shortcut hint (<https://github.com/opencv/cvat/pull/1416>)
- Fixed issue with unnecessary tag activation in cvat-canvas (<https://github.com/opencv/cvat/issues/1540>) - Fixed issue with unnecessary tag activation in cvat-canvas (<https://github.com/opencv/cvat/issues/1540>)
- Fixed an issue with large number of instances in instance mask (https://github.com/opencv/cvat/issues/1539)
- Fixed full COCO dataset import error with conflicting labels in keypoints and detection (https://github.com/opencv/cvat/pull/1548) - Fixed full COCO dataset import error with conflicting labels in keypoints and detection (https://github.com/opencv/cvat/pull/1548)
- Fixed COCO keypoints skeleton parsing and saving (https://github.com/opencv/cvat/issues/1539) - Fixed COCO keypoints skeleton parsing and saving (https://github.com/opencv/cvat/issues/1539)

@ -270,7 +270,7 @@ class CompiledMask:
if instance_ids is not None: if instance_ids is not None:
assert len(instance_ids) == len(instance_masks) assert len(instance_ids) == len(instance_masks)
else: else:
instance_ids = [1 + i for i in range(len(instance_masks))] instance_ids = range(1, len(instance_masks) + 1)
if instance_labels is not None: if instance_labels is not None:
assert len(instance_labels) == len(instance_masks) assert len(instance_labels) == len(instance_masks)
@ -310,15 +310,13 @@ class CompiledMask:
def instance_count(self): def instance_count(self):
return int(self.instance_mask.max()) return int(self.instance_mask.max())
def get_instance_labels(self, class_count=None): def get_instance_labels(self):
if class_count is None: class_shift = 16
class_count = np.max(self.class_mask) + 1 m = (self.class_mask.astype(np.uint32) << class_shift) \
+ self.instance_mask.astype(np.uint32)
m = self.class_mask * class_count + self.instance_mask
m = m.astype(int)
keys = np.unique(m) keys = np.unique(m)
instance_labels = {k % class_count: k // class_count instance_labels = {k & ((1 << class_shift) - 1): k >> class_shift
for k in keys if k % class_count != 0 for k in keys if k & ((1 << class_shift) - 1) != 0
} }
return instance_labels return instance_labels

@ -251,8 +251,7 @@ class VocSegmentationExtractor(_VocExtractor):
if class_mask is not None: if class_mask is not None:
label_cat = self._categories[AnnotationType.label] label_cat = self._categories[AnnotationType.label]
instance_labels = compiled_mask.get_instance_labels( instance_labels = compiled_mask.get_instance_labels()
class_count=len(label_cat.items))
else: else:
instance_labels = {i: None instance_labels = {i: None
for i in range(compiled_mask.instance_count)} for i in range(compiled_mask.instance_count)}

@ -3,6 +3,7 @@ import numpy as np
from unittest import TestCase from unittest import TestCase
import datumaro.util.mask_tools as mask_tools import datumaro.util.mask_tools as mask_tools
from datumaro.components.extractor import CompiledMask
class PolygonConversionsTest(TestCase): class PolygonConversionsTest(TestCase):
@ -184,3 +185,13 @@ class ColormapOperationsTest(TestCase):
self.assertTrue(np.array_equal(expected, actual), self.assertTrue(np.array_equal(expected, actual),
'%s\nvs.\n%s' % (expected, actual)) '%s\nvs.\n%s' % (expected, actual))
def test_can_decode_compiled_mask(self):
class_idx = 1000
instance_idx = 10000
mask = np.array([1])
compiled_mask = CompiledMask(mask * class_idx, mask * instance_idx)
labels = compiled_mask.get_instance_labels()
self.assertEqual({instance_idx: class_idx}, labels)

@ -444,6 +444,41 @@ class VocConverterTest(TestCase):
VocSegmentationConverter(label_map='voc'), test_dir, VocSegmentationConverter(label_map='voc'), test_dir,
target_dataset=DstExtractor()) target_dataset=DstExtractor())
def test_can_save_voc_segm_with_many_instances(self):
def bit(x, y, shape):
mask = np.zeros(shape)
mask[y, x] = 1
return mask
class TestExtractor(TestExtractorBase):
def __iter__(self):
return iter([
DatasetItem(id=1, subset='a', annotations=[
Mask(image=bit(x, y, shape=[10, 10]),
label=self._label(VOC.VocLabel(3).name),
z_order=10 * y + x + 1
)
for y in range(10) for x in range(10)
]),
])
class DstExtractor(TestExtractorBase):
def __iter__(self):
return iter([
DatasetItem(id=1, subset='a', annotations=[
Mask(image=bit(x, y, shape=[10, 10]),
label=self._label(VOC.VocLabel(3).name),
group=10 * y + x + 1
)
for y in range(10) for x in range(10)
]),
])
with TestDir() as test_dir:
self._test_save_and_load(TestExtractor(),
VocSegmentationConverter(label_map='voc'), test_dir,
target_dataset=DstExtractor())
def test_can_save_voc_layout(self): def test_can_save_voc_layout(self):
class TestExtractor(TestExtractorBase): class TestExtractor(TestExtractorBase):
def __iter__(self): def __iter__(self):

Loading…
Cancel
Save