Commit Graph

15 Commits

Author SHA1 Message Date
Adriano 29c034fb05 fix: param edge usati anche in find/ricetta + match overlay solo UCS
Due richieste utente:

1. Param di pulizia rumore (weak/strong/num_features/spacing dal pannello
   "Anteprima edge") devono essere usati anche in find e salvati nelle
   ricette. Prima l'utente li regolava ma erano ignorati: il match usava
   sempre i valori auto_tune.

   Fix:
   - SimpleMatchParams.edge_* (4 campi opzionali): None = usa auto_tune,
     valore = override
   - _simple_to_technical applica gli override se presenti, propagati
     a min_feature_spacing nel matcher init
   - Cache key matcher include min_feature_spacing
   - SaveRecipeParams stessi 4 campi: la ricetta salva i param di
     pulizia rumore identici a quelli del preview
   - UI readEdgeOverrides() legge sempre i valori slider ed inietta
     in body sia di /match_simple sia di POST /recipes

2. Match overlay sulla scena: solo UCS (X rosso, Y verde) ruotato
   secondo m.angle_deg, posizionato sul baricentro feature del
   modello (proiettato alla pose). Niente edge filtrati, niente
   cerchietti feature, niente bbox, niente label/score sulla scena
   reale: l'overlay deve essere pulito, gli edge si vedono solo
   nell'anteprima modello.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 11:37:00 +02:00
Adriano a78884f950 feat(web): anteprima edge sul modello + tracker pulizia rumore + UCS baricentro
Pannello "🔬 Anteprima edge / pulizia rumore" sotto il canvas modello.
Permette tuning interattivo dei parametri di selezione edge per
togliere "sporcizie" (rumore di sfondo, edge spuri) prima di
trainare il matcher.

Server:
- POST /preview_edges: dato modello+ROI+param edge, ritorna immagine
  ROI con overlay:
  * heatmap magnitude gradient (sfondo)
  * verde scuro: pixel sopra hysteresis edge
  * cerchietti colorati per bin: feature scelte (palette 16 bin)
  * UCS rosso/verde sul baricentro feature (richiesta utente):
    asse X destra, Y giu' (image y-down)
  Ritorna anche stats: n_features, n_edge_strong, percentili magnitude,
  ucs_baricentro {cx, cy}

UI:
- Slider weak_grad/strong_grad/num_features/spacing + checkbox polarity
- Re-fetch debounced (200ms) ad ogni input → preview live
- Bottone "Applica ai parametri Avanzate": copia i valori scelti
  nei campi Avanzate del matcher principale
- Auto-fetch quando il pannello viene aperto

Use case: operatore vede SUBITO quali edge il matcher userebbe,
regola soglie per escludere rumore, applica e poi MATCH.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 10:48:58 +02:00
Adriano a12574f3c5 feat(web): pannello diagnostica match (CC) con hint contestuali
MatchResp ora include diag dict (CC feature). UI rendering:

- Nuovo pannello pieghevole "🔍 Diagnostica" sotto i tempi
- Per ogni match mostra:
  * pipeline pruning (vars total → top_eval → top_pass → full_eval)
  * candidati (raw → pre_nms → final)
  * drop reasons (NCC, score, recall, bbox, NMS) con counter
  * soglie effettive applicate
  * flag attivi (polarity, soft, subpix-LM)

- Quando 0 match → pannello si apre automaticamente + mostra hint
  contestuale specifico:
  * "0 candidati top" → suggerisce ↓ min_score / top_thresh
  * "tutti dropped da NCC" → ↓ verify_threshold (filtro_fp)
  * "score post-NCC sotto" → ↓ min_score
  * "recall basso" → ↓ min_recall
  * "bbox out-of-scene" → check pose / search_roi

Risolve il pattern "0 match perche'?" con guida actionable invece
del black-box. Tutti e 3 endpoint match (/match, /match_simple,
/match_recipe) propagano il diag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 10:41:26 +02:00
Adriano b718e81ccf feat(web): UI carica/stacca ricetta + match con ricetta caricata
Manca il path "load" della V feature: utente poteva salvare ricetta
ma non caricarla dalla UI. Aggiunto:

Server:
- POST /recipes/{name}/load: carica .npz in cache _RECIPE_MATCHERS
- POST /match_recipe: usa matcher caricato senza re-train (zero
  training time, solo find params propagati)

UI:
- Dropdown ricette disponibili (auto-refreshed da GET /recipes)
- Bottone "Carica" attiva ricetta + popola state.active_recipe
- Bottone "Stacca" torna al flow normale (training da ROI)
- Status indicator mostra ricetta attiva e dimensioni

doMatch dispatcha automaticamente:
- ricetta attiva → /match_recipe (no model/ROI necessari)
- altrimenti → /match o /match_simple come prima

Use case: ricetta tarata offline, deploy a runtime production senza
ricaricare modello+ROI ogni volta.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 23:20:52 +02:00
Adriano 37c645984f feat(web): bottone Auto-tune nella toolbar (Halcon-style)
UI esponev gia' /auto_tune endpoint ma non c'era trigger user-facing.
Aggiunto bottone toolbar accanto a MATCH:
- Calcola tutti i parametri tecnici dalla ROI selezionata (gradient,
  feature, piramide, angle_step, simmetria)
- Esegue self-validation training+find su template
- Applica i valori derivati ai campi della sezione Avanzate
- Mostra alert con riepilogo + meta diagnostica
  (simmetria detected, self-validation result, ecc.)

Endpoint /auto_tune ora ritorna anche meta (_self_score, _validation,
_symmetry_order, _orient_entropy) per feedback UI invece di filtrarli.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 23:10:07 +02:00
Adriano 6ebb08e7a2 feat(web): wiring UI per modalita Halcon (M, Y, Z, V, X, R + altri)
UI espone tutti i nuovi flag tramite sezione pieghevole "Modalita Halcon"
nel pannello impostazioni. Default off = comportamento backward compat.

Flag esposti (checkbox + numerici):
- use_polarity (F): 16-bin orientation mod 2pi
- use_gpu (R): OpenCL UMat con silent fallback CPU
- use_soft_score (Y): score continuo cos(theta_t-theta_s)
- subpixel_lm (Z): refinement 0.05 px gradient field
- refine_pose_joint: Nelder-Mead 3D (cx,cy,theta)
- pyramid_propagate: top-K propagation a full-res
- min_recall (M): filtro feature-recall
- nms_iou_threshold (A): IoU bbox poligonale
- greediness: early-exit kernel
- coarse_stride: sub-sampling top-level
- search_roi: x,y,w,h area di ricerca

Persistenza ricette (V):
- Endpoint POST /recipes: training + save .npz in recipes/
- Endpoint GET /recipes: lista
- UI: campo nome + bottone "Salva" sotto i flag

Server SimpleMatchParams esteso con tutti i campi; pipeline match_simple
propaga init-flags al cache key (use_polarity/use_gpu = retrain) e
find-flags al m.find().

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 22:49:11 +02:00
Adriano 796ccb8052 fix(web): simmetria invariante (0) collassava a 360 per || default
Bug JS: SYM_MAP[user.simmetria] || 360 trasforma il valore valido 0
(invariante = nessuna rotazione) in 360 = no simmetria. Risultato:
cambiare simmetria nel pannello avanzato non aveva effetto se
selezionato invariante; per le altre opzioni il valore passava
ma con potenziale altri valori 0 in futuro.

Sostituito con ?? per distinguere "chiave mancante" da "valore zero".
Stessa fix per PREC_MAP.

Inoltre allineato FP_MAP JS al server (medio 0.35 -> 0.50, ecc.)
per coerenza UI/backend.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 21:54:16 +02:00
Adriano 3e4c20ecf5 feat: upload file nella cartella IMAGES_DIR
POST /upload_to_folder: sanitizza nome, valida estensione e contenuto
via cv2.imdecode, auto-rename su collisione.
Toolbar UI: bottone 'Carica file', dopo upload ricarica picker.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 14:45:16 +02:00
Adriano cc7d035f66 feat: scale_penalty - score riflette dimensione oltre a forma
Shape matching e invariante scala per design: 3 ruote dentate di dim
diverse avevano tutte score 1.00 confondendo l operatore.

Parametro scale_penalty [0..1]: score_final = score * max(0, 1 - penalty * |scale - 1|)
UI dropdown 'Peso dimensione nel score' con preset 0 / 0.3 / 0.5 / 0.8.

Test rings con penalty 0.5: 1.00 -> 1.00, 0.95 -> 0.97, 0.80 -> 0.90.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 14:37:36 +02:00
Adriano b83e577eab feat: thumbnail picker custom per selezione modello/scena
- GET /folder_image/{filename}?w=N: PNG ridotto cache 1h
- Frontend: 2 thumb-picker al posto dei select (thumb + nome + caret)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 11:10:35 +02:00
Adriano 2bca68d700 feat: 'Filtro falsi positivi' preset user-friendly (era verify_ncc)
Rinomina il parametro tecnico verify_threshold in un preset semantico
che operatore/cliente capisce senza leggere docs:

  off      -> 0.00 (tutti i match shape-based passano)
  leggero  -> 0.20 (tollera illuminazione/riflessi)
  medio    -> 0.35 (consigliato, default)
  forte    -> 0.50 (massima selettivita, scarta mismatch intensita)

UI: dropdown etichettato 'Filtro falsi positivi (verifica intensita colori)'
accanto a precisione angolare. Override tecnico (numerico) resta in
sezione Avanzate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:52:26 +02:00
Adriano 1671a151da feat: selezione immagini da cartella IMAGES_DIR via .env
- .env con IMAGES_DIR=Test
- server: _load_env legge .env senza dip extra
- GET /images lista file, POST /load_from_folder carica per nome
- frontend: file picker sostituiti con 2 select popolati all avvio

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:50:37 +02:00
Adriano 45e3a29ff0 feat: simmetria 'invariante' per oggetti circolari (1 variante angolare)
Test tooth_rim foro grande: 12x piu veloce (0.14s vs 1.77s) perche
angle_max=0 genera 1 sola variante angolare invece di 72.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:02:32 +02:00
Adriano d35bb574ef ui: parametri user-friendly (tipo/simmetria/scala/precisione)
Nascosti i parametri tecnici (num_features, weak/strong_grad, spread,
pyramid) incomprensibili per operatori. Sostituiti da scelte semantiche:

- Tipo modello: intero | parziale
- Simmetria: nessuna | bilaterale (180) | rotazionale 3/4/6/8x
- Variazione scala: fissa | 10% | 25% | 50%
- Precisione: veloce 10 | normale 5 | preciso 2
- Score minimo: slider
- Max match: input

Server: nuovo endpoint POST /match_simple. Deriva tecnici via
_simple_to_technical(roi) che analizza la ROI:
- weak/strong_grad da percentili
- num_features da densita edge x tipo
- pyramid_levels da min(h,w) ROI
- spread_radius proporzionale

Frontend: select + slider, sezione Avanzate collassabile per override.

Test rings_and_nuts preset intero/nessuna/medio/normale: 3/3 ruote in 2.14s

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 09:56:34 +02:00
Adriano fd7585acc5 feat: interfaccia web HTML (FastAPI + canvas JS)
Sostituisce GUI cv2/tkinter con webapp standalone:

Server (pm2d/web/server.py):
- FastAPI + uvicorn
- Endpoint: GET /, POST /upload, POST /match, POST /auto_tune,
  GET /image/{id}/raw
- In-memory image store (uuid-based)
- Rendering annotated server-side via opencv (overlay bbox + edges
  template warpati)

Frontend (pm2d/web/static/):
- index.html: layout 3 colonne (MODELLO | SCENA | PARAMETRI) + footer
  legenda
- style.css: tema dark, CSS grid responsive
- app.js: canvas HTML5 per visualizzazione scalata fit,
  ROI selection con drag mouse, form parametri live,
  MATCH button, Auto-tune button

Parametri modificabili INLINE (niente dialog separata).
Enter su qualsiasi campo triggera MATCH.
Legenda match in fondo con pallino colorato + dati.

main.py ora lancia il server webapp. Deprecato ingresso GUI cv2
(pm2d/gui.py resta importable per backward compat).

Test: /match su rings_and_nuts: 3/3 ruote in 1.14s (train 0.36s + find 0.77s).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 09:06:25 +02:00