Repository: openvinotoolkit/datumaro

Issue:
Bug: concatenation for the different types in COCO format 
https://github.com/openvinotoolkit/datumaro/blob/935fb0ede3c70a68582c7d13b5f5450e51f81235/datumaro/plugins/coco_format/converter.py#L232-L234
masks has type generator, but then we use += between generator and itertools.chain Python doesn't support such concatenation.


Discussion:

Resolving patch:
diff --git a/datumaro/plugins/coco_format/converter.py b/datumaro/plugins/coco_format/converter.py
--- a/datumaro/plugins/coco_format/converter.py
+++ b/datumaro/plugins/coco_format/converter.py
@@ -231,7 +231,7 @@ def find_instance_parts(self, group, img_width, img_height):
             if masks:
                 masks = (m.image for m in masks)
                 if mask is not None:
-                    masks += chain(masks, [mask])
+                    masks = chain(masks, [mask])
                 mask = mask_tools.merge_masks(masks)
 
             if mask is not None:


Test patch:
diff --git a/tests/requirements.py b/tests/requirements.py
--- a/tests/requirements.py
+++ b/tests/requirements.py
@@ -34,6 +34,7 @@ class Requirements:
     DATUM_BUG_314 = "Unsuccessful remap_labels"
     DATUM_BUG_402 = "Troubles running 'remap_labels' on ProjectDataset"
     DATUM_BUG_404 = "custom importer/extractor not loading"
+    DATUM_BUG_425 = "Bug: concatenation for the different types in COCO format"
 
 
 class SkipMessages:
diff --git a/tests/test_coco_format.py b/tests/test_coco_format.py
--- a/tests/test_coco_format.py
+++ b/tests/test_coco_format.py
@@ -1017,3 +1017,44 @@ def test_inplace_save_writes_only_updated_data(self):
             self.assertFalse(osp.isfile(osp.join(path, 'images', 'c', '3.jpg')))
             compare_datasets(self, expected, Dataset.import_from(path, 'coco'),
                 require_images=True, ignored_attrs={'id'})
+
+    @mark_requirement(Requirements. DATUM_BUG_425)
+    def test_can_save_and_load_grouped_masks_and_polygons(self):
+        source_dataset = Dataset.from_iterable([
+            DatasetItem(id=1, image=np.zeros((5, 5, 3)),
+                annotations=[
+                    Mask(np.array([
+                            [0, 0, 0, 0, 0],
+                            [0, 1, 1, 1, 0],
+                            [0, 1, 1, 1, 0],
+                            [0, 1, 1, 1, 0],
+                            [0, 0, 0, 0, 0]],
+                        ),
+                        label=0, id=0, z_order=0, group=1),
+                    Polygon([1, 1, 1, 3, 3, 3, 3, 1],
+                        label=0, id=1, z_order=0, group=1),
+                ]
+            ),
+        ], categories=['label_1'])
+
+        target_dataset = Dataset.from_iterable([
+            DatasetItem(id=1, image=np.zeros((5, 5, 3)),
+                annotations=[
+                    Mask(np.array([
+                            [0, 0, 0, 0, 0],
+                            [0, 1, 1, 1, 0],
+                            [0, 1, 1, 1, 0],
+                            [0, 1, 1, 1, 0],
+                            [0, 0, 0, 0, 0]],
+                        ),
+                        attributes={ 'is_crowd': True },
+                        label=0, id=0, group=1),
+                ], attributes={'id': 1}
+            ),
+        ], categories=['label_1'])
+
+        with TestDir() as test_dir:
+            self._test_save_and_load(source_dataset,
+                 partial(CocoInstancesConverter.convert),
+                 test_dir, target_dataset=target_dataset)
+