"""Test suite esaustivo su Test/*.png con varie configurazioni. Esegue matrix (immagine, ROI completa/parziale, config) e stampa tempi/match. """ from __future__ import annotations import time from pathlib import Path import cv2 import numpy as np from pm2d import LineShapeMatcher from pm2d.gui import draw_matches TEST_DIR = Path(__file__).parent.parent / "Test" OUT_DIR = Path("/tmp/pm2d_suite"); OUT_DIR.mkdir(exist_ok=True) # Casi: (nome, immagine, (y0,y1,x0,x1) roi completa, (y0,y1,x0,x1) roi parziale) CASES = [ ("clip", "clip.png", ( 60, 200, 90, 290), ( 60, 135, 90, 290)), ("ruota", "rings_and_nuts.png", ( 55, 175, 90, 215), ( 55, 115, 90, 215)), ("dado", "rings_and_nuts.png", (255, 375, 40, 170), (255, 315, 40, 170)), ("lama", "razors2.png", ( 90, 370, 120, 160), ( 90, 230, 120, 160)), ] CONFIGS = [ ("fast", dict(angle_step_deg=10.0, scale_range=(1.0, 1.0), pyramid_levels=3, num_features=64)), ("preciso", dict(angle_step_deg=5.0, scale_range=(0.5, 1.1), scale_step=0.05, pyramid_levels=3, num_features=96)), ] def bench(case_name: str, img_path: str, roi_box: tuple, roi_kind: str, cfg_name: str, cfg: dict) -> dict: scene = cv2.imread(str(TEST_DIR / img_path)) y0, y1, x0, x1 = roi_box roi = scene[y0:y1, x0:x1].copy() m = LineShapeMatcher( angle_range_deg=(0.0, 360.0), weak_grad=30, strong_grad=60, spread_radius=5, n_threads=4, **cfg, ) t0 = time.time() n_var = m.train(roi) t_train = time.time() - t0 # warmup (prima call รจ JIT compile) m.find(scene, min_score=0.55, max_matches=3, refine_angle=False) t0 = time.time() matches = m.find( scene, min_score=0.55, max_matches=25, nms_radius=None, refine_angle=True, subpixel=True, verify_threshold=0.4, ) t_find = time.time() - t0 tag = f"{case_name}_{roi_kind}_{cfg_name}" overlay = draw_matches(scene, matches, template_gray=cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)) cv2.imwrite(str(OUT_DIR / f"{tag}.png"), overlay) return { "case": tag, "roi": f"{roi.shape[1]}x{roi.shape[0]}", "variants": n_var, "train_s": t_train, "find_s": t_find, "n_match": len(matches), "score_range": ( f"{min(x.score for x in matches):.2f}..{max(x.score for x in matches):.2f}" if matches else "-" ), } def main(): print(f"{'case':30s} {'roi':>9s} {'var':>4s} " f"{'train':>6s} {'find':>6s} {'n':>3s} score") print("-" * 85) total_find = 0.0 for case_name, img, roi_full, roi_part in CASES: for roi_kind, roi_box in [("full", roi_full), ("part", roi_part)]: for cfg_name, cfg in CONFIGS: r = bench(case_name, img, roi_box, roi_kind, cfg_name, cfg) print(f"{r['case']:30s} {r['roi']:>9s} {r['variants']:>4d} " f"{r['train_s']:>5.2f}s {r['find_s']:>5.2f}s " f"{r['n_match']:>3d} {r['score_range']}") total_find += r["find_s"] print("-" * 85) print(f"totale find: {total_find:.1f}s overlay salvati in {OUT_DIR}/") if __name__ == "__main__": main()