feat: skip track forward on result overlap, not class presence (REQ-189)

Frame holding the tracked class is now annotated like any other; the run's
result is dropped only when it intersects a same-class shape already there.
This commit is contained in:
asus committed 2026-10-06 16:08:54 +07:00
1 parent 3eeb529e3d
commit f5be7880b0
8 files changed
+86 -30

No files matched your search

+21 -1
View File
@@ -320,7 +320,7 @@ def frames_with_auto(batch_id: int) -> set:
def assist(frame_id: int, box: List[float], class_id: int = 0,
threshold: float = 0.5) -> dict:
threshold: float = 0.5, dedupe: bool = False) -> dict:
"""Drag a rough box, get SAM3's shape for the object inside it (REQ-043).
The box is a visual exemplar rather than a crop: SAM3 may return several
@@ -378,6 +378,16 @@ def assist(frame_id: int, box: List[float], class_id: int = 0,
finally:
jobs.gpu_lock.release()
# Track Forward passes dedupe=True (REQ-189): the run still happens, but a
# result that lands on a shape already there is the same object twice, so
# nothing is written and the caller reports the frame as skipped. Runs after
# the lock is released because this part needs no GPU.
if dedupe:
landed = to_box(geometry)
for existing in listing(frame_id):
if existing["class_id"] == class_id and intersects(landed, to_box(existing["geometry"])):
return {"skipped": True}
return add(frame_id, class_id, geometry, source="manual", score=detection.score)
@@ -397,6 +407,16 @@ def _overlap(detection_box: List[float], drawn: List[float],
return inter / (area_box + area_drawn - inter)
def intersects(a: List[float], b: List[float]) -> bool:
"""Any pixel of intersection between two normalized xyxy boxes (REQ-189).
Deliberately not IoU: two trucks that merely touch are two trucks. Raising
this to a ratio is the upgrade path if adjacent same-class boxes ever start
getting dropped as duplicates.
"""
return min(a[2], b[2]) > max(a[0], b[0]) and min(a[3], b[3]) > max(a[1], b[1])
def clear_batch_class_annotations(batch_id: int, class_id: int) -> int:
"""Delete all annotations matching class_id across all frames in a batch (REQ-046)."""
with db.cursor() as cur: