From 616a7fe4e070818108a62af9bbd7d378ca930571 Mon Sep 17 00:00:00 2001 From: Kirill Date: Fri, 27 Aug 2021 10:05:57 +0300 Subject: [PATCH 1/9] Add group for shapes with same track_id --- cvat/apps/dataset_manager/formats/mots.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cvat/apps/dataset_manager/formats/mots.py b/cvat/apps/dataset_manager/formats/mots.py index fc2d69edea99..6ea5889575d7 100644 --- a/cvat/apps/dataset_manager/formats/mots.py +++ b/cvat/apps/dataset_manager/formats/mots.py @@ -50,11 +50,22 @@ def _import(src_file, task_data): frame_number = task_data.abs_frame_id( match_dm_item(item, task_data, root_hint=root_hint)) + shift = 0 + track_ids = set() + for ann in item.annotations: if ann.type != AnnotationType.polygon: continue - track_id = ann.attributes['track_id'] + track_id = ann.attributes['track_id'] + shift + group_id = track_id + + if track_id in track_ids: + shift += 1 + track_id += shift + + track_ids.add(track_id) + shape = task_data.TrackedShape( type='polygon', points=ann.points, @@ -65,6 +76,7 @@ def _import(src_file, task_data): frame=frame_number, attributes=[], source='manual', + group=group_id ) # build trajectories as lists of shapes in track dict From e2a7e3fa23f454ed1f81b6de2cdd4c206fc4f729 Mon Sep 17 00:00:00 2001 From: Kirill Date: Fri, 27 Aug 2021 14:19:32 +0300 Subject: [PATCH 2/9] Replace shift variable --- cvat/apps/dataset_manager/formats/mots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/apps/dataset_manager/formats/mots.py b/cvat/apps/dataset_manager/formats/mots.py index 6ea5889575d7..5fc6408be116 100644 --- a/cvat/apps/dataset_manager/formats/mots.py +++ b/cvat/apps/dataset_manager/formats/mots.py @@ -46,11 +46,11 @@ def _import(src_file, task_data): root_hint = find_dataset_root(dataset, task_data) + shift = 0 for item in dataset: frame_number = task_data.abs_frame_id( match_dm_item(item, task_data, root_hint=root_hint)) - shift = 0 track_ids = set() for ann in item.annotations: From e63cbbcbe2948d8694d868a06411036d1d6a42b0 Mon Sep 17 00:00:00 2001 From: Kirill Date: Mon, 30 Aug 2021 12:06:00 +0300 Subject: [PATCH 3/9] Use negative ids --- cvat/apps/dataset_manager/formats/mots.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cvat/apps/dataset_manager/formats/mots.py b/cvat/apps/dataset_manager/formats/mots.py index 5fc6408be116..9ba5b2268bce 100644 --- a/cvat/apps/dataset_manager/formats/mots.py +++ b/cvat/apps/dataset_manager/formats/mots.py @@ -57,14 +57,15 @@ def _import(src_file, task_data): if ann.type != AnnotationType.polygon: continue - track_id = ann.attributes['track_id'] + shift + track_id = ann.attributes['track_id'] group_id = track_id if track_id in track_ids: - shift += 1 - track_id += shift - - track_ids.add(track_id) + # use negative id for tracks with the same id on the same frame + shift -= 1 + track_id = shift + else: + track_ids.add(track_id) shape = task_data.TrackedShape( type='polygon', From f1e02ba22bac79a1dc566f280d2a43f8beacaeae Mon Sep 17 00:00:00 2001 From: Kirill Date: Tue, 31 Aug 2021 14:33:07 +0300 Subject: [PATCH 4/9] Add unit test --- .../dataset_manager/tests/test_formats.py | 57 ++++++++++++++++--- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/cvat/apps/dataset_manager/tests/test_formats.py b/cvat/apps/dataset_manager/tests/test_formats.py index 8f7edd2f7450..fdc4c04d01d8 100644 --- a/cvat/apps/dataset_manager/tests/test_formats.py +++ b/cvat/apps/dataset_manager/tests/test_formats.py @@ -3,22 +3,24 @@ # # SPDX-License-Identifier: MIT - -from io import BytesIO import os.path as osp import tempfile import zipfile +from io import BytesIO import datumaro +from django.contrib.auth.models import Group, User from PIL import Image -from django.contrib.auth.models import User, Group -from rest_framework.test import APITestCase, APIClient + from rest_framework import status +from rest_framework.test import APIClient, APITestCase import cvat.apps.dataset_manager as dm from cvat.apps.dataset_manager.annotation import AnnotationIR -from cvat.apps.dataset_manager.bindings import TaskData, find_dataset_root, CvatTaskDataExtractor +from cvat.apps.dataset_manager.bindings import (CvatTaskDataExtractor, + TaskData, find_dataset_root) from cvat.apps.dataset_manager.task import TaskAnnotation +from cvat.apps.dataset_manager.util import make_zip_archive from cvat.apps.engine.models import Task @@ -501,7 +503,6 @@ def test_frames_outside_are_not_generated(self): self.assertTrue(frame.frame in range(6, 10)) self.assertEqual(i + 1, 4) - class FrameMatchingTest(_DbTestBase): def _generate_task_images(self, paths): # pylint: disable=no-self-use f = BytesIO() @@ -598,9 +599,10 @@ def _generate_custom_annotations(self, annotations, task): self._put_api_v1_task_id_annotations(task["id"], annotations) return annotations - def _generate_task_images(self, count, name="image"): + def _generate_task_images(self, count, name="image", **kwargs): images = { - "client_files[%d]" % i: generate_image_file("image_%d.jpg" % i) + "client_files[%d]" % i: generate_image_file("%s_%d.jpg" % (name, i), + **kwargs) for i in range(count) } images["image_quality"] = 75 @@ -912,7 +914,44 @@ def test_can_import_annotations_for_image_with_dots_in_filename(self): self._generate_annotations(task, format_name) with self.subTest(format=format_name): - if not f.ENABLED: + if not f.ENABLED or format_name in {'Sly Point Cloud Format 1.0', + 'Kitti Raw Format 1.0'}: self.skipTest("Format is disabled") self._test_can_import_annotations(task, format_name) + + def test_can_import_mots_annotations_with_splited_masks(self): + #https://github.com/openvinotoolkit/cvat/issues/3360 + from datumaro.components.dataset import Dataset, DatasetItem + from datumaro.components.extractor import Mask + from numpy import array + + format_name = 'MOTS PNG 1.0' + source_dataset = Dataset.from_iterable([ + DatasetItem(id='image_0', + annotations=[ + Mask(array([[1, 1, 1, 0, 1, 1, 1]] * 5), + label=0, attributes={'track_id': 0}) + ] + ) + ], categories=['label_0']) + + with tempfile.TemporaryDirectory() as temp_dir: + dataset_dir = osp.join(temp_dir, 'dataset') + source_dataset.export(dataset_dir, 'mots_png') + dataset_path = osp.join(temp_dir, 'annotations.zip') + make_zip_archive(dataset_dir, dataset_path) + + images = self._generate_task_images(1, size=(5, 7)) + task = { + 'name': 'test', + "overlap": 0, + "segment_size": 100, + "labels": [{'name': 'label_0'}] + } + task.update() + task = self._create_task(task, images) + + dm.task.import_task_annotations(task['id'], dataset_path, format_name) + self._test_can_import_annotations(task, format_name) + From aa888d4ed5ae72920325d634d696c9f5d45801dc Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 1 Sep 2021 10:55:19 +0300 Subject: [PATCH 5/9] Rename extra args --- cvat/apps/dataset_manager/tests/test_formats.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cvat/apps/dataset_manager/tests/test_formats.py b/cvat/apps/dataset_manager/tests/test_formats.py index fdc4c04d01d8..432a59d9f97f 100644 --- a/cvat/apps/dataset_manager/tests/test_formats.py +++ b/cvat/apps/dataset_manager/tests/test_formats.py @@ -599,10 +599,10 @@ def _generate_custom_annotations(self, annotations, task): self._put_api_v1_task_id_annotations(task["id"], annotations) return annotations - def _generate_task_images(self, count, name="image", **kwargs): + def _generate_task_images(self, count, name="image", **image_params): images = { "client_files[%d]" % i: generate_image_file("%s_%d.jpg" % (name, i), - **kwargs) + **image_params) for i in range(count) } images["image_quality"] = 75 From 5f3fe455114ccbb8832f6cc3777071253313d0cc Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 1 Sep 2021 11:01:17 +0300 Subject: [PATCH 6/9] Allow dots in image name for 3D formats --- cvat/apps/dataset_manager/bindings.py | 2 +- cvat/apps/dataset_manager/tests/test_formats.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cvat/apps/dataset_manager/bindings.py b/cvat/apps/dataset_manager/bindings.py index 2062e0333fba..fba124b5c887 100644 --- a/cvat/apps/dataset_manager/bindings.py +++ b/cvat/apps/dataset_manager/bindings.py @@ -908,7 +908,7 @@ def _make_image(i, **kwargs): attributes["labels"].append({"label_id": idx, "name": label["name"], "color": label["color"]}) attributes["track_id"] = -1 - dm_item = datumaro.DatasetItem(id=osp.split(frame_data.name)[-1].split('.')[0], + dm_item = datumaro.DatasetItem(id=osp.splitext(osp.split(frame_data.name)[-1])[0], annotations=dm_anno, point_cloud=dm_image[0], related_images=dm_image[1], attributes=attributes) diff --git a/cvat/apps/dataset_manager/tests/test_formats.py b/cvat/apps/dataset_manager/tests/test_formats.py index 432a59d9f97f..158577afd0d0 100644 --- a/cvat/apps/dataset_manager/tests/test_formats.py +++ b/cvat/apps/dataset_manager/tests/test_formats.py @@ -914,8 +914,7 @@ def test_can_import_annotations_for_image_with_dots_in_filename(self): self._generate_annotations(task, format_name) with self.subTest(format=format_name): - if not f.ENABLED or format_name in {'Sly Point Cloud Format 1.0', - 'Kitti Raw Format 1.0'}: + if not f.ENABLED: self.skipTest("Format is disabled") self._test_can_import_annotations(task, format_name) From 243ac14202f6a068e88fd119743ad81ea92653e9 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 1 Sep 2021 11:09:47 +0300 Subject: [PATCH 7/9] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5e168ec4f2a..5f415aa19180 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed multiple tasks moving () - Fixed task creating CLI parameter () +- Fixed import for MOTS format () ### Security From 37a3f15a7541a2d912815826ef7fe8ea57467924 Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 1 Sep 2021 12:20:56 +0300 Subject: [PATCH 8/9] Revert changes in bindings --- cvat/apps/dataset_manager/bindings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat/apps/dataset_manager/bindings.py b/cvat/apps/dataset_manager/bindings.py index fba124b5c887..2062e0333fba 100644 --- a/cvat/apps/dataset_manager/bindings.py +++ b/cvat/apps/dataset_manager/bindings.py @@ -908,7 +908,7 @@ def _make_image(i, **kwargs): attributes["labels"].append({"label_id": idx, "name": label["name"], "color": label["color"]}) attributes["track_id"] = -1 - dm_item = datumaro.DatasetItem(id=osp.splitext(osp.split(frame_data.name)[-1])[0], + dm_item = datumaro.DatasetItem(id=osp.split(frame_data.name)[-1].split('.')[0], annotations=dm_anno, point_cloud=dm_image[0], related_images=dm_image[1], attributes=attributes) From 306c5e1c1bc1b20df5b5c93b2e11911d071e249c Mon Sep 17 00:00:00 2001 From: Kirill Date: Wed, 1 Sep 2021 12:23:55 +0300 Subject: [PATCH 9/9] Fix imports --- cvat/apps/dataset_manager/tests/test_formats.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cvat/apps/dataset_manager/tests/test_formats.py b/cvat/apps/dataset_manager/tests/test_formats.py index 158577afd0d0..69c7e34797ea 100644 --- a/cvat/apps/dataset_manager/tests/test_formats.py +++ b/cvat/apps/dataset_manager/tests/test_formats.py @@ -3,12 +3,15 @@ # # SPDX-License-Identifier: MIT +import numpy as np import os.path as osp import tempfile import zipfile from io import BytesIO import datumaro +from datumaro.components.dataset import Dataset, DatasetItem +from datumaro.components.extractor import Mask from django.contrib.auth.models import Group, User from PIL import Image @@ -921,15 +924,12 @@ def test_can_import_annotations_for_image_with_dots_in_filename(self): def test_can_import_mots_annotations_with_splited_masks(self): #https://github.com/openvinotoolkit/cvat/issues/3360 - from datumaro.components.dataset import Dataset, DatasetItem - from datumaro.components.extractor import Mask - from numpy import array format_name = 'MOTS PNG 1.0' source_dataset = Dataset.from_iterable([ DatasetItem(id='image_0', annotations=[ - Mask(array([[1, 1, 1, 0, 1, 1, 1]] * 5), + Mask(np.array([[1, 1, 1, 0, 1, 1, 1]] * 5), label=0, attributes={'track_id': 0}) ] )