- ov_detector.OVFaceDetector: OV inference + ultralytics letterbox(1280 sq) + greedy NMS; model.predict()-compatible shim, process_video() unchanged - anime_facesaver.py: --gpu igpu branch; CUDA path untouched (moved to else) - CUDA path untouched; main() unchanged - validate_ov.py: cross-check vs torch CPU baseline measured 2026-10-20 i3-N305: 59/59 matched, mean IoU 0.987, only_base=0 only_ov=0; 5.0s/img GPU vs 14.5s/img CPU OpenVINO-CPU vs torch-CPU baseline (25 real stills, yolov8x6_animeface)
42 lines
1.5 KiB
Python
42 lines
1.5 KiB
Python
"""Cross-validate OVFaceDetector vs ultralytics CPU baseline on real stills."""
|
|
import glob, sys, time
|
|
import numpy as np, cv2
|
|
|
|
imgs = sorted(glob.glob('/home/alex/Documents/ov-bench/imgs/*.png'))
|
|
sys.path.insert(0, '.')
|
|
from ov_detector import OVFaceDetector
|
|
|
|
# baseline: ultralytics torch CPU (deterministic on CPU)
|
|
from ultralytics import YOLO
|
|
base = YOLO('models/yolov8x6_animeface.pt')
|
|
|
|
ovd = OVFaceDetector('models/yolov8x6_animeface.onnx', device='GPU', imgsz=1280)
|
|
|
|
def iou(a, b):
|
|
xx1, yy1 = max(a[0], b[0]), max(a[1], b[1])
|
|
xx2, yy2 = min(a[2], b[2]), min(a[3], b[3])
|
|
inter = max(0, xx2-xx1) * max(0, yy2-yy1)
|
|
ua = (a[2]-a[0])*(a[3]-a[1]) + (b[2]-b[0])*(b[3]-b[1]) - inter
|
|
return inter / max(ua, 1e-9)
|
|
|
|
ious, n_match, n_only_base, n_only_ov = [], 0, 0, 0
|
|
t0=time.time()
|
|
for p in imgs:
|
|
fr = cv2.imread(p)
|
|
rb = base.predict(fr, conf=0.25, imgsz=1280, device='cpu', verbose=False)[0]
|
|
ro = ovd.predict(fr, conf=0.25, imgsz=1280, verbose=False)[0]
|
|
bb = rb.boxes.xyxy.cpu().numpy() if rb.boxes is not None else np.zeros((0,4))
|
|
bo = ro.boxes.xyxy.numpy()
|
|
used = set()
|
|
for box in bb:
|
|
best, bi = 0, -1
|
|
for j, ob in enumerate(bo):
|
|
v = iou(box, ob)
|
|
if v > best: best, bi = v, j
|
|
if best > 0.5:
|
|
ious.append(best); n_match += 1; used.add(bi)
|
|
else: n_only_base += 1
|
|
n_only_ov += len(bo) - len(used)
|
|
dt = time.time()-t0
|
|
print(f"imgs={len(imgs)} matched={n_match} (mean IoU {np.mean(ious):.3f}) only_base={n_only_base} only_ov={n_only_ov} [{dt:.0f}s total]")
|