Handle two-frame Ego4D bbox tails and preserve worker errors

This commit is contained in:
Xin Wang
2026-08-28 09:26:45 +08:00
parent 668996bfa8
commit 18e8773685
5 changed files with 156 additions and 40 deletions
+18 -9
View File
@@ -27,6 +27,9 @@ from local_turn_features import (
TESTED_TRANSFORMERS_VERSIONS = ("4.52.3", "4.57.6")
# Verified Ego4D exports can retain one or two bbox frame indices after the
# media endpoint. This bounds frame positions, not the number of people/boxes.
EGO4D_MAX_TERMINAL_FRAME_OVERRUN = 2
def validate_local_transformers_version(version: str) -> str:
@@ -191,12 +194,13 @@ def load_ego4d_boxes(paths: list[Path], names: list[str]) -> dict[str, Any]:
def validate_ego4d_box_frames(name: str, annotation: dict[str, Any], source):
"""Ignore only a confirmed exclusive-end record; never shift/clamp boxes."""
"""Ignore a bounded, boundary-confirmed tail; never shift/clamp boxes."""
frames, bounds = annotation["frames"], annotation["bounds"]
count = source.num_frames
outside = sorted(frame for frame in frames if not 0 <= frame < count)
audit = {
"policy": "clip-local-zero-based; ignore-confirmed-exclusive-end-only",
"policy": "clip-local-zero-based; ignore-confirmed-tail-up-to-2-frames",
"max_terminal_frame_overrun": EGO4D_MAX_TERMINAL_FRAME_OVERRUN,
"source_frames": count, "source_fps": source.source_fps,
"declared_bounds": dict(bounds),
"annotation_frame_range": [min(frames), max(frames)] if frames else None,
@@ -211,22 +215,27 @@ def validate_ego4d_box_frames(name: str, annotation: dict[str, Any], source):
and source.source_fps > 0 and abs(start_sec) <= 1e-6
and abs((end_sec - start_sec) - count / source.source_fps) <= 1e-4
)
if (outside != [count] or bounds.get("clip_start_frame") != 0
# Allow only N and N+1. Counting outliers alone would accidentally permit
# sparse but arbitrarily distant boxes; the maximum index must be bounded.
small_terminal_tail = count <= outside[0] <= outside[-1] < count + EGO4D_MAX_TERMINAL_FRAME_OVERRUN
if (not small_terminal_tail or bounds.get("clip_start_frame") != 0
or bounds.get("clip_end_frame") != count or not duration_matches):
raise ValueError(
f"Ego4D annotation frame exceeds source clip: {name}; "
f"source_frames={count}, source_fps={source.source_fps}, "
f"annotation_range={audit['annotation_frame_range']}, "
f"out_of_range_count={len(outside)}, first_10={outside[:10]}, "
f"declared_bounds={bounds}. Only frame == source_frames == clip_end_frame "
"with zero-origin, matching duration is an allowed terminal record; "
f"declared_bounds={bounds}. Only terminal indices in "
f"[{count}, {count + EGO4D_MAX_TERMINAL_FRAME_OVERRUN - 1}] "
"with source_frames == clip_end_frame, zero origin and matching duration are allowed; "
"check annotation/video alignment instead of clamping or skipping the clip."
)
audit.update(ignored_frame_indices=[count], ignored_box_count=len(frames[count]))
print(f"{name}: ignoring exclusive-end bbox record at frame {count} "
f"({len(frames[count])} boxes); decoded frames are 0..{count - 1}. "
ignored_boxes = sum(len(frames[frame]) for frame in outside)
audit.update(ignored_frame_indices=outside, ignored_box_count=ignored_boxes)
print(f"{name}: ignoring terminal bbox frame indices {outside} "
f"({ignored_boxes} boxes); decoded frames are 0..{count - 1}. "
"No frame shift or feature/target row removal.", flush=True)
return {frame: boxes for frame, boxes in frames.items() if frame != count}, audit
return {frame: boxes for frame, boxes in frames.items() if 0 <= frame < count}, audit
def build_media_and_boxes(args: argparse.Namespace, name: str, end: float, ego_boxes: dict[str, Any]):