Spaces:
Sleeping
Sleeping
| #!/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() | |