# Roadmap - Possibili Sviluppi Lista ragionata di miglioramenti futuri. Priorità = impatto / effort, non urgenza temporale. ## Fase 2 COMPLETATA (precisione rotazione + robustezza + perf) Root cause della rotazione imprecisa: lo score satura a 1.0 sulla spread bitmap dilatata (raggio 4-5) → il refine non vedeva gradiente né in angolo né in posizione, e `cv2.minMaxLoc` sul plateau saturo spostava il centro sull'angolo della finestra (errore sistematico 3·√2 ≈ 4.24 px). | Fix | Dettaglio | |---|---| | Refine su bitmap fine | `_refine_angle` ottimizza su spread raggio 1 (`spread_fine`, cached); score finale ricalcolato su spread coarse per mantenere semantica soglie | | Picco sub-pixel nel refine | centroide plateau / fit quadratico al posto di minMaxLoc (bias top-left) | | LM least-squares pos+angolo | `_subpixel_refine_lm` riscritto: snap edge ±2px lungo normale + LSQ 3x3 (dx, dy, dθ), ON di default | | Round feature offsets | troncamento `astype(int32)` → `np.round` (bias ~0.25 px) | | Centro rotazione coerente | `_prepare_padded_template`: rotazione attorno al centro reale del template nel padding (bias ≤0.5 px dipendente dall'angolo) | | `_angle_list` include estremo | range parziali ±tol ora testano anche +tol | | `_refine_pose_joint` rimosso | Nelder-Mead su funzione a gradini satura: terminava subito; param ora alias di refine_angle | | pyramid_propagate di default | kernel windowed (feature campionano l'intera scena: prima il crop troncava le feature → score 0); picchi = massimi locali (non top-K pixel); disattivato automaticamente per template elongati (>2:1) dove il picco top-level non localizza | | Piramide 3 livelli default | con clamp automatico sulla dimensione template (min 12 px al top) | | Cache scena: hash completo | prima hashava solo i primi 64KB → collisioni tra scene con stessa banda superiore → risultati della scena sbagliata | | Web server | lock matcher (race con threadpool FastAPI), LRU `_IMG_CACHE`, clamp ROI ovunque (400/422 invece di 500), `filtro_fp=off` disabilita davvero NCC, `_draw_matches` su crop locale | | GUI/legacy | centro overlay `(W-1)/2`→`W/2`, spread_radius default 5→4, EdgeShapeMatcher: angle list endpoint + cap candidati + save template_gray | Misure (GT sintetica 7 pose, scena 900x700, VPS 2 core): - Errore angolare mediano: **2.3° → 0.05°** (step 5°); a step 2° era 4.4° → **0.03°** - Errore posizione mediano: **4.24 px → 0.04 px** - find GT scene: 4.7s → 1.7s; scena reale 646x482: 1.14s → 0.81s - Benchmark suite 16 scenari: 96.5s → 84.2s, match count ≥ baseline (eccezioni: dado_full -1 = match borderline su parte diversa; lama_part_preciso 25→18 con baseline al cap max_matches) ## Fase 1 COMPLETATA (branch `speedFase1`) | ID | Voce | Status | Note | |---|---|---|---| | V1 | Coarse-to-fine angolare (step coarse al top-level) | ✅ | `coarse_angle_factor=2` default, safe anche su template allungati | | V11 | Cache matcher in-memory LRU (capacità 8) | ✅ | Key = hash(ROI bytes + params). Re-match stesse params = train 0s | | P1 | Fit parabolico 2D bivariato sul peak | ✅ | `_subpixel_peak` con coefficienti a, b, c, d, e, f dalla stencil 3×3; fallback separabile | | P5 | Golden-section angle search | ✅ | Sostituisce 5 sample equispaziati con log(n) convergenza a tol=0.1° | | P2 | Weighted centroid del plateau | ✅ | Integrato in `_subpixel_peak` con peso = (score - soglia)² | Benchmark suite 16 scenari (4 immagini × full/part × fast/preciso): - Prima Fase 1: totale find 27.3s - Dopo Fase 1: totale find 25.1s (~8% speedup) - Regressione match count: nessuna (alcuni casi +1 match grazie a subpixel migliore) - Match auto-referenziale: offset 0.00 px, angolo 0.000° (era -3.5 px, -2.5°) ## Performance CPU | Sviluppo | Effort | Speed-up atteso | Dipendenze | Priorità | |---|---|---|---|---| | Numba JIT su `_score_by_shift` | basso | 3-5× | numba (~200MB) | alta | | Numba JIT su `_response_map` | basso | 2-3× | numba | alta | | FFT-based score per varianti dense | medio | 2× su template grandi | scipy | media | | Rewrite `_score_by_shift` in Cython | alto | 5-8× | cython build | bassa | | SIMD via `pypy` runtime | medio | 2-4× | pypy interpreter | bassa (dipendenza runtime) | | Memory layout: struct-of-arrays compatto int8 | medio | 1.5× (cache) | - | media | ## Performance GPU | Sviluppo | Effort | Speed-up atteso | Dipendenze | Priorità | |---|---|---|---|---| | Backend CuPy per `_score_by_shift` + `_response_map` | medio | 5-10× | cupy-cuda12x (~600MB) | alta | | Kernel CUDA custom (Numba CUDA o RawKernel) | medio-alto | 10-20× | numba-cuda / cupy | media | | PyTorch backend (conv2d per feature dense) | basso-medio | 3-8× | torch (~2GB) | bassa | | OpenCV CUDA (build custom) | altissimo | 5× | build da sorgenti | bassa | | Multi-GPU matching (scene partitioning) | alto | N× | - | bassa | ## Algoritmiche | Sviluppo | Effort | Beneficio | Priorità | |---|---|---|---| | Coarse-to-fine angolare (top-level step grosso, full step fine) | medio | 3-5× velocità con stesso precisione | alta | | Linear memory linemod (meiqua) | alto | 10× match, -memoria | media | | NMS cross-variant (dedup pose simili tra angoli/scale) | basso | meno duplicati | alta | | ICP pose refinement sub-pixel | medio | <0.1 px precisione | media | | Score calibrato probabilistico | medio | soglia adattiva | media | | Rilevazione simmetria rotazionale robusta | medio | angle_range auto ridotto | alta | | Template piramidato con feature per livello | fatto | ✓ | - | | Refinement angolare sub-step | fatto | ✓ | - | | Subpixel posizione (parabolic fit) | fatto | ✓ | - | | Multi-template support (modello con varianti) | medio | generalizzazione | media | | Confidence ellipse (uncertainty quantification) | basso | diagnostic | bassa | ## Feature di prodotto | Sviluppo | Effort | Beneficio | Priorità | |---|---|---|---| | Supporto DXF (tassellazione + rasterizzazione via ezdxf) | medio | input CAD | alta | | ROI poligonale (non rettangolare) nella GUI | basso | modello parziale preciso | alta | | Analisi distintività modello (entropia, self-corr) nella UI | basso | warning al training | media | | Salvataggio/caricamento modello `.npz` con thumbnail | basso | ricette riusabili | alta | | Batch matching su cartella scene | basso | throughput offline | media | | Esportazione JSON risultati per integrazione | basso | pipeline | alta | | Live camera matching (webcam) | basso-medio | demo | bassa | | REST API wrapper (FastAPI) | medio | integrazione Vision Suite | media | | NATS messaging (per Vision Suite) | medio | microservizio | bassa | | Web UI (Gradio o React) sostituiva di tk/cv2 | alto | deploy remoto | media | | Benchmark suite automatica con GT labels | medio | non-regression | alta | ## Qualità codice | Sviluppo | Effort | Beneficio | Priorità | |---|---|---|---| | Unit test (pytest) con dataset sintetico | basso | robustezza | alta | | Type annotations complete + mypy strict | basso | manutenibilità | media | | CI GitHub Actions: lint + test + build | medio | qualità PR | media | | Profiling automatico baseline + regression check | medio | evitare lentezze | bassa | | Packaging pip (`pip install pm2d`) | basso | distribuzione | bassa | ## Target performance produzione Obiettivi da documento tecnico Vision Suite (Fase Beta): - [x] **Precisione posizionale mediana**: <0.5 px → **0.04 px misurato su GT sintetica (Fase 2)** - [x] **Precisione angolare mediana**: <1.0° → **0.05° misurato su GT sintetica (Fase 2)** - [ ] **Latency mediana**: <50 ms su 1920×1080 → **~0.8s su 646×482 con 2 core; da misurare su hardware produzione** - [ ] **F1 score dataset sintetico**: >0.95 → **da misurare con dataset sintetico** Prossimo blocker per target: **latency**. Nota: i kernel hot sono gia' Numba JIT (≈ velocita' C, prange parallelo): un port C++ dei kernel vale solo il margine SIMD esplicito (~2-4x con AVX2 su AND+popcount byte-wise). Prima di scriverlo conviene esaurire le vie algoritmiche rimaste: riduzione varianti al top-level (auto angle step per livello, stile Halcon), greediness di default, e GPU (CuPy/OpenCL) per scene 1080p.