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)