Zion Boggan
repos/Pitch Tracker CV/tools/yolo_collect_frames.py
zionboggan.com ↗
71 lines · python
History for this file →
1
"""Capture live frames for one-class MLB baseball YOLO training.
2
 
3
Saves raw frames to datasets/mlb26_ball_yolo/images/all. Label these images
4
with class 0 = ball, then run yolo_split_dataset.py.
5
"""
6
from __future__ import annotations
7
 
8
import argparse
9
import shutil
10
import sys
11
import time
12
from pathlib import Path
13
 
14
import cv2
15
from rich.console import Console
16
 
17
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
18
from capture.ingest import open_capture
19
from cv._common import load_config
20
 
21
ROOT = Path(__file__).resolve().parents[1]
22
OUT_DIR = ROOT / "datasets" / "mlb26_ball_yolo" / "images" / "all"
23
console = Console()
24
 
25
def main() -> int:
26
    ap = argparse.ArgumentParser(description="Capture frames for YOLO ball labeling.")
27
    ap.add_argument("--duration", type=float, default=120.0, help="Capture duration in seconds.")
28
    ap.add_argument("--fps", type=float, default=12.0, help="Saved frame rate.")
29
    ap.add_argument("--clear", action="store_true", help="Clear images/all before capture.")
30
    ap.add_argument("--prefix", default="mlb26", help="Output filename prefix.")
31
    args = ap.parse_args()
32
 
33
    if args.clear and OUT_DIR.exists():
34
        shutil.rmtree(OUT_DIR)
35
    OUT_DIR.mkdir(parents=True, exist_ok=True)
36
 
37
    cap = open_capture(load_config())
38
    if cap is None or not cap.isOpened():
39
        console.print("[red]Could not open capture card.[/red]")
40
        return 2
41
 
42
    interval = 1.0 / max(args.fps, 0.1)
43
    deadline = time.perf_counter() + args.duration
44
    next_save = time.perf_counter()
45
    saved = 0
46
    read_count = 0
47
 
48
    console.print(f"[cyan]Capturing {args.duration:.0f}s at {args.fps:.1f} saved fps -> {OUT_DIR}[/cyan]")
49
    try:
50
        while time.perf_counter() < deadline:
51
            ok, frame = cap.read()
52
            if not ok or frame is None:
53
                continue
54
            read_count += 1
55
            now = time.perf_counter()
56
            if now < next_save:
57
                continue
58
            out = OUT_DIR / f"{args.prefix}_{int(time.time() * 1000)}_{saved:05d}.jpg"
59
            cv2.imwrite(str(out), frame, [cv2.IMWRITE_JPEG_QUALITY, 95])
60
            saved += 1
61
            next_save = now + interval
62
            if saved % 50 == 0:
63
                console.print(f"  saved {saved} frames")
64
    finally:
65
        cap.release()
66
 
67
    console.print(f"[green]Saved {saved} frames. Capture reads: {read_count}.[/green]")
68
    return 0
69
 
70
if __name__ == "__main__":
71
    raise SystemExit(main())