Skip to content

Commit

Permalink
Fix 2827 (#2890)
Browse files Browse the repository at this point in the history
* Fix 2827

* update changelog
  • Loading branch information
Maxim Zhiltsov authored Mar 3, 2021
1 parent 4191ea2 commit 5e6a51a
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed of receiving function variable (<https://github.com/openvinotoolkit/cvat/pull/2860>)
- Shortcuts with CAPSLOCK enabled and with non-US languages activated (<https://github.com/openvinotoolkit/cvat/pull/2872>)
- Fixed label editor name field validator (<https://github.com/openvinotoolkit/cvat/pull/2879>)
- An error about track shapes outside of the task frames during export (<https://github.com/openvinotoolkit/cvat/pull/2890>)

### Security

Expand Down
6 changes: 5 additions & 1 deletion cvat/apps/dataset_manager/annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def filter_track_shapes(shapes):
# Track and TrackedShape models don't expect these fields
del track['interpolated_shapes']
for shape in segment_shapes:
del shape['keyframe']
shape.pop('keyframe', None)

track['shapes'] = segment_shapes
track['frame'] = track['shapes'][0]['frame']
Expand Down Expand Up @@ -746,6 +746,10 @@ def interpolate(shape0, shape1):
curr_frame = shape["frame"]
prev_shape = shape

# keep at least 1 shape
if end_frame <= curr_frame:
break

if not prev_shape["outside"]:
shape = copy(prev_shape)
shape["frame"] = end_frame
Expand Down
5 changes: 5 additions & 0 deletions cvat/apps/dataset_manager/bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ def get_frame(idx):
anno_manager = AnnotationManager(self._annotation_ir)
for shape in sorted(anno_manager.to_shapes(self._db_task.data.size),
key=lambda shape: shape.get("z_order", 0)):
if shape['frame'] not in self._frame_info:
# After interpolation there can be a finishing frame
# outside of the task boundaries. Filter it out to avoid errors.
# https://github.com/openvinotoolkit/cvat/issues/2827
continue
if 'track_id' in shape:
if shape['outside']:
continue
Expand Down
58 changes: 55 additions & 3 deletions cvat/apps/dataset_manager/tests/test_formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ def _put_api_v1_task_id_annotations(self, tid, data):

return response

def _put_api_v1_job_id_annotations(self, jid, data):
with ForceLogin(self.user, self.client):
response = self.client.put("/api/v1/jobs/%s/annotations" % jid,
data=data, format="json")

return response

def _create_task(self, data, image_data):
with ForceLogin(self.user, self.client):
response = self.client.post('/api/v1/tasks', data=data, format="json")
Expand All @@ -87,6 +94,10 @@ def _create_task(self, data, image_data):
return task

class TaskExportTest(_DbTestBase):
def _generate_custom_annotations(self, annotations, task):
self._put_api_v1_task_id_annotations(task["id"], annotations)
return annotations

def _generate_annotations(self, task):
annotations = {
"version": 0,
Expand Down Expand Up @@ -204,8 +215,7 @@ def _generate_annotations(self, task):
},
]
}
self._put_api_v1_task_id_annotations(task["id"], annotations)
return annotations
return self._generate_custom_annotations(annotations, task)

def _generate_task_images(self, count): # pylint: disable=no-self-use
images = {
Expand All @@ -215,7 +225,7 @@ def _generate_task_images(self, count): # pylint: disable=no-self-use
images["image_quality"] = 75
return images

def _generate_task(self, images):
def _generate_task(self, images, **overrides):
task = {
"name": "my task #1",
"overlap": 0,
Expand All @@ -242,6 +252,7 @@ def _generate_task(self, images):
{"name": "person"},
]
}
task.update(overrides)
return self._create_task(task, images)

@staticmethod
Expand Down Expand Up @@ -422,6 +433,47 @@ def test_can_make_abs_frame_id_from_known(self):

self.assertEqual(5, task_data.abs_frame_id(2))

def test_frames_outside_are_not_generated(self):
# https://github.com/openvinotoolkit/cvat/issues/2827
images = self._generate_task_images(10)
images['start_frame'] = 0
task = self._generate_task(images, overlap=3, segment_size=6)
annotations = {
"version": 0,
"tags": [],
"shapes": [],
"tracks": [
{
"frame": 6,
"label_id": task["labels"][0]["id"],
"group": None,
"source": "manual",
"attributes": [],
"shapes": [
{
"frame": 6,
"points": [1.0, 2.1, 100, 300.222],
"type": "rectangle",
"occluded": False,
"outside": False,
"attributes": [],
},
]
},
]
}
self._put_api_v1_job_id_annotations(
task["segments"][2]["jobs"][0]["id"], annotations)

task_ann = TaskAnnotation(task["id"])
task_ann.init_from_db()
task_data = TaskData(task_ann.ir_data, Task.objects.get(pk=task['id']))

i = -1
for i, frame in enumerate(task_data.group_by_frame()):
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()
Expand Down

0 comments on commit 5e6a51a

Please sign in to comment.