Skip to content

Commit bcc4dbe

Browse files
authored
validate extracted start-label first frame
1 parent 6a5d7eb commit bcc4dbe

2 files changed

Lines changed: 44 additions & 28 deletions

File tree

poseinterface/clips.py

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@ def _cliplabels_suffix_error(name: str) -> str:
2121
return f"Input file must end with '_cliplabels.json', got {name}"
2222

2323

24+
def _extract_start_labels(clip_labels: dict) -> dict:
25+
start_images = [img for img in clip_labels["images"] if img["id"] == 0]
26+
if len(start_images) != 1:
27+
raise ValueError(
28+
"Clip labels must contain exactly one image with id 0"
29+
)
30+
31+
return {
32+
"images": start_images,
33+
"annotations": [
34+
annot
35+
for annot in clip_labels["annotations"]
36+
if annot["image_id"] == 0
37+
],
38+
"categories": clip_labels["categories"],
39+
}
40+
41+
2442
def extract_clip(
2543
video_path: str | Path,
2644
start_frame: int,
@@ -228,19 +246,7 @@ def extract_start_frames_label(cliplabels_path: str | Path) -> Path:
228246
with open(cliplabels_path) as f:
229247
clip_labels = json.load(f)
230248

231-
# Extract only the first frame's data (frame with id=0)
232-
start_labels = {}
233-
start_labels["images"] = [
234-
img for img in clip_labels["images"] if img["id"] == 0
235-
]
236-
237-
# Extract only annotations for the first frame (image_id=0)
238-
start_labels["annotations"] = [
239-
annot for annot in clip_labels["annotations"] if annot["image_id"] == 0
240-
]
241-
242-
# Keep categories unchanged
243-
start_labels["categories"] = clip_labels["categories"]
249+
start_labels = _extract_start_labels(clip_labels)
244250

245251
# Generate output path by replacing _cliplabels.json with _startlabels.json
246252
output_path = cliplabels_path.parent / cliplabels_path.name.replace(
@@ -329,21 +335,7 @@ def extract_start_frames_label_s3(
329335
response = s3_client.get_object(Bucket=bucket_name, Key=key)
330336
clip_labels = json.loads(response["Body"].read().decode("utf-8"))
331337

332-
# Extract only the first frame's data (frame with id=0)
333-
start_labels = {}
334-
start_labels["images"] = [
335-
img for img in clip_labels["images"] if img["id"] == 0
336-
]
337-
338-
# Extract only annotations for the first frame (image_id=0)
339-
start_labels["annotations"] = [
340-
annot
341-
for annot in clip_labels["annotations"]
342-
if annot["image_id"] == 0
343-
]
344-
345-
# Keep categories unchanged
346-
start_labels["categories"] = clip_labels["categories"]
338+
start_labels = _extract_start_labels(clip_labels)
347339

348340
# Generate output key by replacing _cliplabels.json with
349341
# _startlabels.json

tests/test_unit/test_clips.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from poseinterface.clips import (
99
_extract_cliplabels,
10+
_extract_start_labels,
1011
extract_clip,
1112
main,
1213
parse_args,
@@ -157,6 +158,29 @@ def test_extract_clip_invalid(
157158
extract_clip(video_path, start_frame, duration)
158159

159160

161+
def test_extract_start_labels(video_labels):
162+
"""Test start labels contain only the first frame and its annotations."""
163+
start_labels = _extract_start_labels(video_labels)
164+
165+
assert start_labels["images"] == [{"id": 0}]
166+
assert start_labels["annotations"] == [
167+
{"image_id": 0, "id": j} for j in range(5)
168+
]
169+
assert start_labels["categories"] == video_labels["categories"]
170+
171+
172+
def test_extract_start_labels_requires_first_frame(video_labels):
173+
"""Test start-label extraction validates the presence of frame 0."""
174+
clip_labels = {
175+
**video_labels,
176+
"images": [{"id": 1}],
177+
"annotations": [{"image_id": 1, "id": 1}],
178+
}
179+
180+
with pytest.raises(ValueError, match="exactly one image with id 0"):
181+
_extract_start_labels(clip_labels)
182+
183+
160184
def test_parse_args():
161185
"""Check arguments are parsed with correct types"""
162186
video_path = "foo.mp4"

0 commit comments

Comments
 (0)