Skip to content

Commit

Permalink
Fix gt job frames in complex setups
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiltsov-max committed Jun 9, 2023
1 parent 080fa8e commit 8a4ed6c
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 5 deletions.
4 changes: 2 additions & 2 deletions cvat/apps/engine/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,8 +672,8 @@ def create(self, validated_data):
)

segment = models.Segment.objects.create(
start_frame=task.data.start_frame,
stop_frame=task.data.stop_frame,
start_frame=0,
stop_frame=task.data.size,
frames=frames,
task=task,
type=models.SegmentType.SPECIFIC_FRAMES,
Expand Down
2 changes: 1 addition & 1 deletion cvat/apps/engine/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1915,7 +1915,7 @@ def metadata(self, request, pk):
stop_frame = db_job.segment.stop_frame
frame_step = db_data.get_frame_step()
data_start_frame = db_data.start_frame + start_frame * frame_step
data_stop_frame = db_data.start_frame + stop_frame * frame_step
data_stop_frame = min(db_data.stop_frame, db_data.start_frame + stop_frame * frame_step)
frame_set = db_job.segment.frame_set

if request.method == 'PATCH':
Expand Down
56 changes: 54 additions & 2 deletions tests/python/rest_api/test_jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@
from PIL import Image

from shared.utils.config import make_api_client
from shared.utils.helpers import generate_image_files

from .utils import CollectionSimpleFilterTestBase, compare_annotations, export_dataset
from .utils import CollectionSimpleFilterTestBase, compare_annotations, create_task, export_dataset


def get_job_staff(job, tasks, projects):
Expand Down Expand Up @@ -577,7 +578,9 @@ def test_can_get_gt_job_meta(self, admin_user, tasks, task_mode):
assert job_frame_ids == gt_job_meta.included_frames

# The frames themselves are the same as in the whole range
# this is required in UI implementation
# this is required by the UI implementation
assert task_meta.start_frame == gt_job_meta.start_frame
assert task_meta.stop_frame == gt_job_meta.stop_frame
if task_mode == "annotation":
assert (
len(gt_job_meta.frames)
Expand All @@ -588,6 +591,52 @@ def test_can_get_gt_job_meta(self, admin_user, tasks, task_mode):
else:
assert False

@pytest.mark.usefixtures("restore_db_per_function")
def test_can_get_gt_job_meta_with_complex_frame_setup(self, admin_user):
image_count = 50
start_frame = 3
stop_frame = image_count - 4
frame_step = 5

images = generate_image_files(image_count)

task_id, _ = create_task(
admin_user,
spec={
"name": "test complex frame setup",
"labels": [{"name": "cat"}],
},
data={
"image_quality": 75,
"start_frame": start_frame,
"stop_frame": stop_frame,
"frame_filter": f"step={frame_step}",
"client_files": images,
"sorting_method": "predefined",
},
)

task_frame_ids = range(start_frame, stop_frame, frame_step)
job_frame_ids = list(task_frame_ids[::3])
gt_job = self._get_or_create_gt_job(admin_user, task_id, job_frame_ids)

with make_api_client(admin_user) as api_client:
(gt_job_meta, _) = api_client.jobs_api.retrieve_data_meta(gt_job.id)

# The size is adjusted by the frame step and included frames
assert len(job_frame_ids) == gt_job_meta.size
assert job_frame_ids == gt_job_meta.included_frames

# The frames themselves are the same as in the whole range
# with placeholders in the frames outside the job.
# This is required by the UI implementation
assert start_frame == gt_job_meta.start_frame
assert max(task_frame_ids) == gt_job_meta.stop_frame
assert [frame_info["name"] for frame_info in gt_job_meta.frames] == [
images[frame].name if frame in job_frame_ids else "placeholder.jpg"
for frame in task_frame_ids
]

@pytest.mark.parametrize("task_mode", ["annotation", "interpolation"])
@pytest.mark.parametrize("quality", ["compressed", "original"])
def test_can_get_gt_job_chunk(self, admin_user, tasks, task_mode, quality):
Expand Down Expand Up @@ -622,6 +671,9 @@ def test_can_get_gt_job_chunk(self, admin_user, tasks, task_mode, quality):
)
included_frames = job_frame_ids

# The frame count is the same as in the whole range
# with placeholders in the frames outside the job.
# This is required by the UI implementation
with zipfile.ZipFile(chunk_file) as chunk:
assert set(chunk.namelist()) == set("{:06d}.jpeg".format(i) for i in frame_range)

Expand Down

0 comments on commit 8a4ed6c

Please sign in to comment.