Spaces:
Sleeping
Sleeping
File size: 2,649 Bytes
78738de | 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 | """Test phần THUẦN của poolcoach_cv.overlay (lát A2 phần 3) — venv app,
không cv2/torch: RecordingModel (ghi bbox quanh predict) + _uncomp_xy
(nghịch đảo bù độ cao — vẽ ngược lên frame phải ra chỗ bi HIỆN RA).
Render thật nghiệm thu bằng smoke trên clip cú 03 rack_a1 (venv CV,
13/08) + gate A2.2 khi rerun trọn VOD.
"""
from __future__ import annotations
import numpy as np
import pytest
from poolcoach_cv.camera import HeightCompensation
from poolcoach_cv.overlay import BALL_BGR, RecordingModel, _uncomp_xy
class _Box:
def __init__(self, cls_i, conf, xyxy):
self.cls = cls_i
self.conf = conf
self.xyxy = [xyxy]
class _Res:
names = {0: "Cue", 1: "Solid"}
def __init__(self, boxes):
self.boxes = boxes
class _FakeYolo:
def predict(self, imgs, **kw):
# mỗi ảnh 1 kết quả — ảnh thứ hai không có det nào
out = [_Res([_Box(0, 0.9, (10.0, 20.0, 30.0, 40.0)),
_Box(1, 0.8, (50.0, 60.0, 70.0, 80.0))])]
out += [_Res([]) for _ in imgs[1:]]
return out
def test_recording_model_ghi_bbox_theo_thu_tu_frame():
rec = RecordingModel(_FakeYolo())
res = rec.predict(["f0", "f1"], conf=0.3, imgsz=640, verbose=False)
assert len(res) == 2 # forward nguyên kết quả
assert len(rec.frames) == 2
assert rec.frames[0] == [("Cue", 0.9, (10.0, 20.0, 30.0, 40.0)),
("Solid", 0.8, (50.0, 60.0, 70.0, 80.0))]
assert rec.frames[1] == []
rec.predict(["f2"], conf=0.3)
assert len(rec.frames) == 3 # batch sau nối tiếp, không đè
def test_uncomp_xy_dao_dung_bu_do_cao():
"""apply (bù) rồi _uncomp_xy (đảo) phải về đúng toạ độ map gốc — vẽ
ngược qua homography mới trúng chỗ bi hiện ra trên frame."""
comp = HeightCompensation(True, cam_xy=(0.6, 1.2), h_m=2.41,
f_px=2236.0, ball_r=0.028575)
raw = np.array([[0.2, 0.4], [1.1, 2.3]])
compensated = comp.apply(raw)
meta = {"on": True, "h_m": 2.41, "cx_m": 0.6, "cy_m": 1.2}
assert _uncomp_xy(compensated, meta) == pytest.approx(raw, abs=1e-9)
def test_uncomp_xy_off_hay_thieu_camera_giu_nguyen():
pts = np.array([[0.5, 0.5]])
assert _uncomp_xy(pts, {"on": False}) is pts
assert _uncomp_xy(pts, None) is pts
# on nhưng thiếu cx/cy (kết quả thời kỳ BG31 trước BG32) — không đoán
assert _uncomp_xy(pts, {"on": True, "h_m": 2.4}) is pts
def test_bang_mau_bi_du_1_den_9():
assert set(BALL_BGR) == set(range(1, 10))
|