| 1 | """Scan every burst frame for PCI-like green pixels; report per-frame counts.""" |
| 2 | from __future__ import annotations |
| 3 | |
| 4 | import sys |
| 5 | from pathlib import Path |
| 6 | |
| 7 | import cv2 |
| 8 | import numpy as np |
| 9 | from rich.console import Console |
| 10 | |
| 11 | console = Console() |
| 12 | BURST_DIR = Path(__file__).resolve().parents[1] / "logs" / "burst" |
| 13 | |
| 14 | def main() -> int: |
| 15 | lo = np.array([45, 140, 140], np.uint8) |
| 16 | hi = np.array([75, 255, 255], np.uint8) |
| 17 | frames = sorted(BURST_DIR.glob("burst_*.png")) |
| 18 | console.print(f"scanning {len(frames)} frames with HSV {list(lo)}..{list(hi)}") |
| 19 | hits = [] |
| 20 | for f in frames: |
| 21 | img = cv2.imread(str(f)) |
| 22 | if img is None: |
| 23 | continue |
| 24 | hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) |
| 25 | h, w = img.shape[:2] |
| 26 | mask = cv2.inRange(hsv, lo, hi) |
| 27 | |
| 28 | window = np.zeros_like(mask) |
| 29 | window[int(0.3 * h):int(0.75 * h), int(0.35 * w):int(0.65 * w)] = 255 |
| 30 | mask = cv2.bitwise_and(mask, window) |
| 31 | n = int((mask > 0).sum()) |
| 32 | if n >= 100: |
| 33 | hits.append((f.name, n)) |
| 34 | hits.sort(key=lambda x: -x[1]) |
| 35 | console.print(f"[bold]Found {len(hits)} frames with >=100 central green px:[/bold]") |
| 36 | for name, n in hits[:15]: |
| 37 | console.print(f" {name} {n} px") |
| 38 | return 0 |
| 39 | |
| 40 | if __name__ == "__main__": |
| 41 | sys.exit(main()) |