#!/usr/bin/env python3 """ Diagnose why the punt at 6107s (1:41:47) wasn't detected. The freeze→25 detection fires at 6117.9s, but no play was started between 6065.4s (previous play end) and 6117.9s. Why? """ import json import logging import sys from pathlib import Path import cv2 # Add src to path sys.path.insert(0, str(Path(__file__).parent.parent / "src")) from detection.scorebug import DetectScoreBug from readers import ReadPlayClock from setup import DigitTemplateLibrary, PlayClockRegionConfig, PlayClockRegionExtractor logging.basicConfig(level=logging.INFO, format="%(message)s") logger = logging.getLogger(__name__) # Video and config paths VIDEO_PATH = Path("/Users/andytaylor/Documents/Personal/cfb40/full_videos/OSU vs Oregon 01.01.25.mkv") CONFIG_PATH = Path("/Users/andytaylor/Documents/Personal/cfb40/output/OSU_vs_Oregon_01_01_25_config.json") TEMPLATE_DIR = Path("/Users/andytaylor/Documents/Personal/cfb40/output/debug/digit_templates") # Time window to analyze: 6060s to 6125s START_TIME = 6060 END_TIME = 6125 def main(): # Load config with open(CONFIG_PATH, "r") as f: config = json.load(f) # Set up fixed coordinates scorebug_bbox = ( config["scorebug_x"], config["scorebug_y"], config["scorebug_width"], config["scorebug_height"], ) playclock_coords = ( config["scorebug_x"] + config["playclock_x_offset"], config["scorebug_y"] + config["playclock_y_offset"], config["playclock_width"], config["playclock_height"], ) template_path = config["template_path"] print(f"Video: {VIDEO_PATH}") print(f"Scorebug bbox: {scorebug_bbox}") print(f"Playclock coords: {playclock_coords}") print() # Initialize components scorebug_detector = DetectScoreBug(template_path=template_path, fixed_region=scorebug_bbox, use_split_detection=True) # Load digit templates template_library = DigitTemplateLibrary() if not template_library.load(str(TEMPLATE_DIR)): print(f"ERROR: Could not load digit templates from {TEMPLATE_DIR}") return clock_reader = ReadPlayClock(template_library, config["playclock_width"], config["playclock_height"]) # Open video cap = cv2.VideoCapture(str(VIDEO_PATH)) fps = cap.get(cv2.CAP_PROP_FPS) frame_interval = 0.5 # Same as main pipeline print(f"FPS: {fps:.2f}, Frame interval: {frame_interval}s") print() print(f"{'Time':>10} | {'Clock':>6} | {'SB Det':>7} | {'SB Match':>8} | {'Notes'}") print("-" * 60) # Track state last_clock = None freeze_start = None freeze_value = None current_time = START_TIME while current_time <= END_TIME: frame_num = int(current_time * fps) cap.set(cv2.CAP_PROP_POS_FRAMES, frame_num) ret, frame = cap.read() if not ret or frame is None: print(f"{current_time:>10.1f} | {'???':>6} | {'NO FRAME':>7} |") current_time += frame_interval continue # Detect scorebug scorebug = scorebug_detector.detect(frame) # Read clock clock_value = None sb_det = "No" sb_match = "N/A" notes = [] if scorebug.detected: sb_det = "Yes" sb_match = "Yes" if scorebug.template_matched else "No" clock_result = clock_reader.read_from_fixed_location(frame, playclock_coords, padding=4) if clock_result and clock_result.detected and clock_result.value is not None: clock_value = clock_result.value # Track freeze if last_clock == clock_value: if freeze_start is None: freeze_start = current_time - frame_interval freeze_value = clock_value freeze_duration = current_time - freeze_start if freeze_duration > 0.5: notes.append(f"frozen {freeze_duration:.1f}s") else: # Clock changed if freeze_start is not None and clock_value == 25 and freeze_value is not None and freeze_value <= 24: freeze_duration = current_time - freeze_start notes.append(f"*** FREEZE→25 from {freeze_value} (frozen {freeze_duration:.1f}s) ***") freeze_start = None freeze_value = None # Check for play start indicators if clock_value == 40: notes.append("*** CLOCK AT 40 - should trigger play start ***") if clock_value == 25 and last_clock is not None and last_clock != 25: notes.append(f"jump to 25 from {last_clock}") last_clock = clock_value else: sb_det = "No" sb_match = "N/A" notes.append("scorebug not detected") # Reset tracking when scorebug lost freeze_start = None freeze_value = None time_str = f"{current_time:.1f}s" clock_str = str(clock_value) if clock_value is not None else "???" note_str = " | ".join(notes) if notes else "" print(f"{time_str:>10} | {clock_str:>6} | {sb_det:>7} | {sb_match:>8} | {note_str}") current_time += frame_interval cap.release() print() print("Analysis complete.") if __name__ == "__main__": main()