From 49fb25730c0f83544d1e17e1b9051243c77d4568 Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Fri, 29 May 2020 13:21:54 +0300 Subject: [PATCH 1/2] use absolute frame numbers in interface --- cvat/apps/dataset_manager/bindings.py | 37 ++++++++++++------------ cvat/apps/dataset_manager/formats/mot.py | 4 +-- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/cvat/apps/dataset_manager/bindings.py b/cvat/apps/dataset_manager/bindings.py index d8152086b496..21a53b9d43ee 100644 --- a/cvat/apps/dataset_manager/bindings.py +++ b/cvat/apps/dataset_manager/bindings.py @@ -97,16 +97,21 @@ def _get_mutable_attribute_id(self, label_id, attribute_name): def _get_immutable_attribute_id(self, label_id, attribute_name): return self._get_attribute_id(label_id, attribute_name, 'immutable') + def abs_frame_id(self, relative_id): + return relative_id * self._frame_step + self._db_task.data.start_frame + + def rel_frame_id(self, absolute_id): + return (absolute_id - self._db_task.data.start_frame) // self._frame_step + def _init_frame_info(self): if hasattr(self._db_task.data, 'video'): self._frame_info = {frame: { - "path": "frame_{:06d}".format( - self._db_task.data.start_frame + frame * self._frame_step), + "path": "frame_{:06d}".format(self.abs_frame_id(frame)), "width": self._db_task.data.video.width, "height": self._db_task.data.video.height, } for frame in range(self._db_task.data.size)} else: - self._frame_info = {db_image.frame: { + self._frame_info = {self.rel_frame_id(db_image.frame): { "path": db_image.path, "width": db_image.width, "height": db_image.height, @@ -193,8 +198,7 @@ def _export_attributes(self, attributes): def _export_tracked_shape(self, shape): return TaskData.TrackedShape( type=shape["type"], - frame=self._db_task.data.start_frame + - shape["frame"] * self._frame_step, + frame=self.abs_frame_id(shape["frame"]), label=self._get_label_name(shape["label_id"]), points=shape["points"], occluded=shape["occluded"], @@ -210,8 +214,7 @@ def _export_labeled_shape(self, shape): return TaskData.LabeledShape( type=shape["type"], label=self._get_label_name(shape["label_id"]), - frame=self._db_task.data.start_frame + - shape["frame"] * self._frame_step, + frame=self.abs_frame_id(shape["frame"]), points=shape["points"], occluded=shape["occluded"], z_order=shape.get("z_order", 0), @@ -221,8 +224,7 @@ def _export_labeled_shape(self, shape): def _export_tag(self, tag): return TaskData.Tag( - frame=self._db_task.data.start_frame + - tag["frame"] * self._frame_step, + frame=self.abs_frame_id(tag["frame"]), label=self._get_label_name(tag["label_id"]), group=tag.get("group", 0), attributes=self._export_attributes(tag["attributes"]), @@ -232,7 +234,7 @@ def group_by_frame(self, include_empty=False): frames = {} def get_frame(idx): frame_info = self._frame_info[idx] - frame = self._db_task.data.start_frame + idx * self._frame_step + frame = self.abs_frame_id(idx) if frame not in frames: frames[frame] = TaskData.Frame( idx=idx, @@ -299,8 +301,7 @@ def meta(self): def _import_tag(self, tag): _tag = tag._asdict() label_id = self._get_label_id(_tag.pop('label')) - _tag['frame'] = (int(_tag['frame']) - - self._db_task.data.start_frame) // self._frame_step + _tag['frame'] = self.rel_frame_id(int(_tag['frame'])) _tag['label_id'] = label_id _tag['attributes'] = [self._import_attribute(label_id, attrib) for attrib in _tag['attributes'] @@ -316,8 +317,7 @@ def _import_attribute(self, label_id, attribute): def _import_shape(self, shape): _shape = shape._asdict() label_id = self._get_label_id(_shape.pop('label')) - _shape['frame'] = (int(_shape['frame']) - - self._db_task.data.start_frame) // self._frame_step + _shape['frame'] = self.rel_frame_id(int(_shape['frame'])) _shape['label_id'] = label_id _shape['attributes'] = [self._import_attribute(label_id, attrib) for attrib in _shape['attributes'] @@ -327,14 +327,13 @@ def _import_shape(self, shape): def _import_track(self, track): _track = track._asdict() label_id = self._get_label_id(_track.pop('label')) - _track['frame'] = (min(int(shape.frame) for shape in _track['shapes']) - - self._db_task.data.start_frame) // self._frame_step + _track['frame'] = self.rel_frame_id( + min(int(shape.frame) for shape in _track['shapes'])) _track['label_id'] = label_id _track['attributes'] = [] _track['shapes'] = [shape._asdict() for shape in _track['shapes']] for shape in _track['shapes']: - shape['frame'] = (int(shape['frame']) - \ - self._db_task.data.start_frame) // self._frame_step + shape['frame'] = self.rel_frame_id(int(shape['frame'])) _track['attributes'] = [self._import_attribute(label_id, attrib) for attrib in shape['attributes'] if self._get_immutable_attribute_id(label_id, attrib.name)] @@ -564,7 +563,7 @@ def import_dm_annotations(dm_dataset, task_data): label_cat = dm_dataset.categories()[datumaro.AnnotationType.label] for item in dm_dataset: - frame_number = match_frame(item, task_data) + frame_number = task_data.abs_frame_id(match_frame(item, task_data)) # do not store one-item groups group_map = {0: 0} diff --git a/cvat/apps/dataset_manager/formats/mot.py b/cvat/apps/dataset_manager/formats/mot.py index 4731284a75c4..7cc7c0ae43ee 100644 --- a/cvat/apps/dataset_manager/formats/mot.py +++ b/cvat/apps/dataset_manager/formats/mot.py @@ -40,7 +40,7 @@ def _import(src_file, task_data): for item in dataset: item = item.wrap(id=int(item.id) - 1) # NOTE: MOT frames start from 1 - frame_id = match_frame(item, task_data) + frame_number = task_data.abs_frame_id(match_frame(item, task_data)) for ann in item.annotations: if ann.type != datumaro.AnnotationType.bbox: @@ -57,7 +57,7 @@ def _import(src_file, task_data): outside=False, keyframe=False, z_order=ann.z_order, - frame=frame_id, + frame=frame_number, attributes=[], ) From 9e4eddb5e8a5a3cf54c470c44d8f1ba0d409977a Mon Sep 17 00:00:00 2001 From: Maxim Zhiltsov Date: Fri, 29 May 2020 13:27:56 +0300 Subject: [PATCH 2/2] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3945039c3526..86e2e2c9877c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Synchronization with remote git repo () - A problem with mask to polygons conversion when polygons are too small () - Unable to upload video with uneven size () +- Problem with exported frame stepped image task (https://github.com/opencv/cvat/issues/1613) ### Security -