feat: GDINO A+B — time-bounded search (9s vs 130s) + parameterized interval
This commit is contained in:
@@ -17,7 +17,8 @@ def find_trace_by_identity(actor_name, file_uuid):
|
||||
conn = psycopg2.connect("postgresql://accusys@localhost:5432/momentry")
|
||||
cur = conn.cursor()
|
||||
cur.execute("""
|
||||
SELECT fd.trace_id, COUNT(*) as faces
|
||||
SELECT fd.trace_id, COUNT(*) as faces,
|
||||
MIN(fd.frame_number) as start_f, MAX(fd.frame_number) as end_f
|
||||
FROM dev.face_detections fd
|
||||
JOIN dev.identities i ON i.id = fd.identity_id
|
||||
WHERE i.name = %s AND fd.file_uuid = %s AND fd.trace_id IS NOT NULL
|
||||
@@ -27,7 +28,9 @@ def find_trace_by_identity(actor_name, file_uuid):
|
||||
row = cur.fetchone()
|
||||
cur.close()
|
||||
conn.close()
|
||||
return row[0] if row else None
|
||||
if row:
|
||||
return {"trace_id": row[0], "faces": row[1], "start_frame": row[2], "end_frame": row[3]}
|
||||
return None
|
||||
|
||||
|
||||
def find_trace_in_frame_range(start_frame, end_frame, file_uuid):
|
||||
@@ -115,24 +118,32 @@ def execute(query, file_uuid):
|
||||
print(f" [{qid}] ({qtype}) {query['prompt'][:55]}...", end="", flush=True)
|
||||
|
||||
# Type-specific search
|
||||
trace_id = None
|
||||
trace_info = None
|
||||
if qtype == "identity":
|
||||
actor = query.get("expected_identity")
|
||||
if actor:
|
||||
trace_id = find_trace_by_identity(actor, file_uuid)
|
||||
trace_info = find_trace_by_identity(actor, file_uuid)
|
||||
elif qtype == "scene":
|
||||
start = query.get("cut_start", 0)
|
||||
end = query.get("cut_end", 1000000)
|
||||
trace_id = find_trace_in_frame_range(start, end, file_uuid)
|
||||
if trace_id:
|
||||
trace_info = {"trace_id": trace_id}
|
||||
elif qtype == "object":
|
||||
obj = query.get("expected_object", "")
|
||||
trace_id = find_trace_by_object(obj, file_uuid)
|
||||
if trace_id:
|
||||
trace_info = {"trace_id": trace_id}
|
||||
|
||||
if trace_id is None:
|
||||
if trace_info is None:
|
||||
print(" ❌ no trace found")
|
||||
return {"query": query, "status": "no_trace", "frames": []}
|
||||
|
||||
print(f" trace={trace_id}", end="", flush=True)
|
||||
trace_id = trace_info["trace_id"] if isinstance(trace_info, dict) else trace_info
|
||||
start_frame = trace_info.get("start_frame", 0) if isinstance(trace_info, dict) else 0
|
||||
end_frame = trace_info.get("end_frame", 0) if isinstance(trace_info, dict) else 0
|
||||
trace_start = start_frame / 25.0 if start_frame > 0 else 0
|
||||
trace_end = end_frame / 25.0 if end_frame > 0 else trace_start + 30
|
||||
|
||||
# Download video
|
||||
vid_path = f"{FRAME_OUTPUT}/{qid}_video.mp4"
|
||||
@@ -152,5 +163,7 @@ def execute(query, file_uuid):
|
||||
"status": "ok",
|
||||
"trace_id": trace_id,
|
||||
"video_path": vid_path,
|
||||
"frames": frames
|
||||
"frames": frames,
|
||||
"trace_start": trace_start,
|
||||
"trace_end": trace_end,
|
||||
}
|
||||
|
||||
@@ -5,18 +5,20 @@ from PIL import Image
|
||||
GDINO_URL = "http://localhost:5051/search"
|
||||
DEFAULT_UUID = "aeed71342a899fe4b4c57b7d41bcb692"
|
||||
|
||||
def score(frames, prompt):
|
||||
def score(frames, prompt, start_time=0, end_time=0):
|
||||
prompt_lower = prompt.lower()
|
||||
|
||||
# Just do a single time-bounded search (not per frame)
|
||||
# Time-bounded search using GDINO range (format "start-end")
|
||||
search_range = f"{int(start_time)}-{int(end_time) if end_time > start_time else int(start_time) + 60}"
|
||||
|
||||
try:
|
||||
resp = requests.post(GDINO_URL, json={
|
||||
"file_uuid": DEFAULT_UUID,
|
||||
"text": prompt_lower,
|
||||
"limit": 3,
|
||||
"start_time": 0,
|
||||
"end_time": 0
|
||||
}, timeout=30)
|
||||
"uuid": DEFAULT_UUID,
|
||||
"query": prompt_lower,
|
||||
"range": search_range,
|
||||
"interval": 10,
|
||||
"threshold": 0.1,
|
||||
}, timeout=60)
|
||||
data = resp.json()
|
||||
hits = data.get("hits", [])
|
||||
n_hits = len(hits)
|
||||
@@ -31,7 +33,7 @@ def score(frames, prompt):
|
||||
return {
|
||||
"agent": "GroundingDINO",
|
||||
"score": score_val,
|
||||
"reasoning": f"{n_hits} hits, best_score={best_score:.2f}, labels={dets_found[:3]}",
|
||||
"reasoning": f"{n_hits} hits, range={search_range}, best={best_score:.2f}",
|
||||
"details": {"n_hits": n_hits, "best_score": best_score}
|
||||
}
|
||||
except Exception as e:
|
||||
|
||||
@@ -64,8 +64,19 @@ def run_judges(query, result, file_uuid):
|
||||
print(f" ERROR: {str(e)[:60]}")
|
||||
results.append({"agent": "MaskFormer", "score": 50, "reasoning": f"Judge error: {str(e)[:60]}", "details": {}})
|
||||
|
||||
# Grounding DINO — SKIP (too slow per-video search)
|
||||
results.append({"agent": "GroundingDINO", "score": 50, "reasoning": "Skipped (too slow for full-video search)", "details": {}})
|
||||
# Grounding DINO — time-bounded search
|
||||
print(f" [{qid}] GDINO...", end="", flush=True)
|
||||
try:
|
||||
gd_result = gdino.score(
|
||||
frames, prompt,
|
||||
start_time=result.get("trace_start", 0),
|
||||
end_time=result.get("trace_end", 0)
|
||||
)
|
||||
print(" done")
|
||||
results.append(gd_result)
|
||||
except Exception as e:
|
||||
print(f" ERROR: {str(e)[:60]}")
|
||||
results.append({"agent": "GroundingDINO", "score": 50, "reasoning": f"Judge error", "details": {}})
|
||||
|
||||
print(f" [{qid}] FaceNet...", end="", flush=True)
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user