Ottimizzazioni cumulative (225s -> 73s sul bench suite, 3.07x):
pm2d/line_matcher.py:
- Sub-pixel + plateau centroid spostati DOPO il pre-NMS (prima: 58k chiamate
per clip_preciso anche su candidati poi scartati dalla NMS; ora solo sui
~75 preliminary sopravvissuti). Coordinate intere OK per la decisione
reject, dato che nms_radius >= 8 px.
- Usa nuovo kernel fuso score+rescore (no allocazione intermedia).
- Adaptive plateau_radius + propagazione train_mask per NCC coerente.
- Local crop NCC (diag template invece di intera scena).
- Fallback adattivo se bg_rescore azzera tutti gli score top-level.
pm2d/_jit_kernels.py:
- Nuovo kernel _jit_score_bitmap_rescored: fonde scoring bitmap e rescore
(score - bg) / (1 - bg) in un singolo pass parallelo. Evita allocazione
e passata aggiuntiva (era ~15% del tempo find sul preciso).
pm2d/auto_tune.py:
- LRU cache in-memory sui risultati auto_tune (chiave md5 ROI + mask):
richiamate successive con stessa ROI sono O(1).
- Downsample a 128px prima della correlazione rotazionale
(O(n_angles * H * W) -> insensibile su sample moderati).
- Soglie weak/strong da percentili reali (p55/p85) senza clamp a 100,
con clamp massimo 400 per evitare saturazione su template ad alto contrasto.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Problema: matcher linemod con solo orientamento gradient può dare score alto
su texture dense/rumore che per caso accumulano orientamenti compatibili.
Esempio: template ruota dentata su scena clip → match a score 0.9 (errati).
Fix in 2 livelli:
1. Background score LOCALE nel find()
- _bg_map(resp, box_size) = densità media bin attivi in bbox template
- Rinormalizza score: s' = max(0, (s - bg) / (1 - bg))
- Annulla contributo di zone sature ma preserva pattern puliti
2. Verify NCC post-hoc
- _verify_ncc(): warpa template alla pose (cx, cy, angle, scale) e
calcola NCC classico su intensità con la scena sottostante
- Threshold di default 0.4 elimina FP con edge orientati casualmente
- Parametro esposto in GUI (verify_threshold)
Rimossa penalty di saturazione nel response_map (ridondante).
Test regression (ruote dentate vs clip, clip vs ruote dentate):
no verify: 12+ falsi positivi con score ~0.7
verify 0.4: 1-2 falsi positivi rimanenti, true positive invariati
verify 0.5: 0 falsi positivi, 1 TP scale piccola perso
Benchmark clip→clip (13 istanze):
full pipeline (Numba + threads + refine + subpix + verify): 1.12s
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>