From 4c603504b74c2b82c3facb482aa39d56ff1b6a98 Mon Sep 17 00:00:00 2001 From: zhiltsov-max Date: Fri, 22 May 2020 11:25:48 +0300 Subject: [PATCH] Add VOC grayscale masks test and documentation (#1576) * Add a test for unpainted masks * Update format documentation --- cvat/apps/dataset_manager/formats/README.md | 20 ++++++++++++ datumaro/tests/test_voc_format.py | 34 +++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/cvat/apps/dataset_manager/formats/README.md b/cvat/apps/dataset_manager/formats/README.md index 56a5dfad..2879eaa4 100644 --- a/cvat/apps/dataset_manager/formats/README.md +++ b/cvat/apps/dataset_manager/formats/README.md @@ -322,6 +322,26 @@ Uploaded file: a zip archive of the following structure: └── image2.png ``` +It is also possible to import grayscale (1-channel) PNG masks. +For grayscale masks provide a list of labels with the number of lines equal +to the maximum color index on images. The lines must be in the right order +so that line index is equal to the color index. Lines can have arbitrary, +but different, colors. If there are gaps in the used color +indices in the annotations, they must be filled with arbitrary dummy labels. +Example: +``` +q:0,128,0:: # color index 0 +aeroplane:10,10,128:: # color index 1 +_dummy2:2,2,2:: # filler for color index 2 +_dummy3:3,3,3:: # filler for color index 3 +boat:108,0,100:: # color index 3 +... +_dummy198:198,198,198:: # filler for color index 198 +_dummy199:199,199,199:: # filler for color index 199 +... +the last label:12,28,0:: # color index 200 +``` + - supported shapes: Polygons #### How to create a task from Pascal VOC dataset diff --git a/datumaro/tests/test_voc_format.py b/datumaro/tests/test_voc_format.py index 7bb4d082..56470884 100644 --- a/datumaro/tests/test_voc_format.py +++ b/datumaro/tests/test_voc_format.py @@ -444,6 +444,40 @@ class VocConverterTest(TestCase): VocSegmentationConverter(label_map='voc'), test_dir, target_dataset=DstExtractor()) + def test_can_save_voc_segm_unpainted(self): + class TestExtractor(TestExtractorBase): + def __iter__(self): + return iter([ + DatasetItem(id=1, subset='a', annotations=[ + # overlapping masks, the first should be truncated + # the second and third are different instances + Mask(image=np.array([[0, 1, 1, 1, 0]]), label=4, + z_order=1), + Mask(image=np.array([[1, 1, 0, 0, 0]]), label=3, + z_order=2), + Mask(image=np.array([[0, 0, 0, 1, 0]]), label=3, + z_order=2), + ]), + ]) + + class DstExtractor(TestExtractorBase): + def __iter__(self): + return iter([ + DatasetItem(id=1, subset='a', annotations=[ + Mask(image=np.array([[0, 0, 1, 0, 0]]), label=4, + group=1), + Mask(image=np.array([[1, 1, 0, 0, 0]]), label=3, + group=2), + Mask(image=np.array([[0, 0, 0, 1, 0]]), label=3, + group=3), + ]), + ]) + + with TestDir() as test_dir: + self._test_save_and_load(TestExtractor(), + VocSegmentationConverter(label_map='voc', apply_colormap=False), + test_dir, target_dataset=DstExtractor()) + def test_can_save_voc_segm_with_many_instances(self): def bit(x, y, shape): mask = np.zeros(shape)