Spaces:
Sleeping
Sleeping
File size: 5,482 Bytes
aa2c8ff 1386d71 aa2c8ff | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | #!/usr/bin/env python3
"""
Test template matching on 10-minute segment (38:40-48:40).
v3 baseline shows 13 plays in this segment.
This test verifies:
1. Template matching detects >= 13 plays (no regression)
2. Significant speed improvement over OCR
Usage:
cd /Users/andytaylor/Documents/Personal/cfb40
source .venv/bin/activate
python tests/test_digit_templates/test_full_segment.py
"""
import logging
import sys
from pathlib import Path
from pipeline.play_detector import PlayDetector, DetectionConfig
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
# Test configuration
VIDEO_PATH = "full_videos/OSU vs Tenn 12.21.24.mkv"
TEMPLATE_PATH = "output/OSU_vs_Tenn_12_21_24_template.png"
PLAYCLOCK_CONFIG_PATH = "output/OSU_vs_Tenn_12_21_24_playclock_config.json"
# 10-minute test segment: 38:40 to 48:40
START_TIME = 38 * 60 + 40 # 2320 seconds
END_TIME = 48 * 60 + 40 # 2920 seconds
# v3 baseline: 13 plays in this segment
EXPECTED_MIN_PLAYS = 13
# v3 baseline OCR time for 10 min would be ~52s (based on 312.7s for full video)
# Target: < 20s for template matching (including template building)
TARGET_TIME = 20.0
def test_full_segment():
"""Test template matching on 10-minute segment."""
logger.info("=" * 60)
logger.info("TEST: 10-Minute Segment (38:40-48:40)")
logger.info("=" * 60)
# Check files exist
for path, name in [(VIDEO_PATH, "Video"), (TEMPLATE_PATH, "Template"), (PLAYCLOCK_CONFIG_PATH, "Config")]:
if not Path(path).exists():
logger.error("%s not found: %s", name, path)
return False
# Create detection config with template matching
config = DetectionConfig(
video_path=VIDEO_PATH,
template_path=TEMPLATE_PATH,
clock_region_config_path=PLAYCLOCK_CONFIG_PATH,
start_time=START_TIME,
end_time=END_TIME,
frame_interval=0.5,
use_template_matching=True,
template_collection_frames=400, # Use first 400 frames for template building
)
logger.info("\nConfiguration:")
logger.info(" Segment: %.1fs - %.1fs (%.1f minutes)", START_TIME, END_TIME, (END_TIME - START_TIME) / 60)
logger.info(" Template matching: ENABLED")
logger.info(" Expected plays (v3 baseline): >= %d", EXPECTED_MIN_PLAYS)
# Run detection
logger.info("\n[Step 1] Running detection pipeline...")
detector = PlayDetector(config)
# Set fixed region from known scorebug location
detector.scorebug_detector.set_fixed_region((128, 975, 1669, 46))
result = detector.detect()
# Analyze results
logger.info("\n[Step 2] Analyzing results...")
logger.info(" Total frames processed: %d", result.total_frames_processed)
logger.info(" Frames with scorebug: %d (%.1f%%)", result.frames_with_scorebug, 100 * result.frames_with_scorebug / max(1, result.total_frames_processed))
logger.info(" Frames with clock: %d (%.1f%%)", result.frames_with_clock, 100 * result.frames_with_clock / max(1, result.total_frames_processed))
logger.info(" Plays detected: %d", len(result.plays))
# Timing analysis
total_time = sum(result.timing.values())
template_building_time = result.timing.get("template_building", 0)
template_matching_time = result.timing.get("template_matching", 0)
ocr_time = result.timing.get("playclock_ocr", 0)
logger.info("\nTiming breakdown:")
for key, value in result.timing.items():
if value > 0:
pct = 100 * value / total_time if total_time > 0 else 0
logger.info(" %s: %.2fs (%.1f%%)", key, value, pct)
logger.info(" TOTAL: %.2fs", total_time)
# Speed comparison
# v3 baseline OCR time estimate for 10 min segment
# Full video (8777s) took 312.7s for OCR, so 10 min (600s) would take ~21.4s for OCR alone
estimated_ocr_time = 312.7 * (END_TIME - START_TIME) / 8777
actual_clock_time = template_building_time + template_matching_time + ocr_time
logger.info("\nSpeed comparison:")
logger.info(" Estimated OCR-only time (v3): %.1fs", estimated_ocr_time)
logger.info(" Actual clock reading time: %.1fs", actual_clock_time)
if actual_clock_time > 0:
speedup = estimated_ocr_time / actual_clock_time
logger.info(" Speedup: %.1fx", speedup)
# List all plays
logger.info("\nDetected plays:")
for play in result.plays:
play_time = play.get("start_time", 0)
duration = play.get("duration", 0)
play_type = play.get("play_type", "unknown")
logger.info(" Play #%d: %.1fs - %.1fs (%.1fs) [%s]", play.get("play_number", 0), play_time, play.get("end_time", 0), duration, play_type)
# Check success criteria
plays_ok = len(result.plays) >= EXPECTED_MIN_PLAYS
time_ok = total_time <= TARGET_TIME
logger.info("\n" + "=" * 60)
logger.info("TEST SUMMARY")
logger.info("=" * 60)
logger.info("Plays detected: %d (target: >= %d) - %s", len(result.plays), EXPECTED_MIN_PLAYS, "PASS" if plays_ok else "FAIL")
logger.info("Processing time: %.2fs (target: <= %.1fs) - %s", total_time, TARGET_TIME, "PASS" if time_ok else "FAIL")
passed = plays_ok # Only require play count, time is informational
if passed:
logger.info("\nTEST: PASSED")
else:
logger.info("\nTEST: FAILED")
return passed
if __name__ == "__main__":
success = test_full_segment()
sys.exit(0 if success else 1)
|