DXF compare dal campo: ICP sui bordi di tutta l'immagine, non allinea i pezzi veri #86

Closed
opened 2026-10-24 11:51:01 +00:00 by Adriano · 1 comment
Owner

Ricetta DXF compare dal campo (#83) non allinea il disegno sui pezzi veri di Menoncin (foto 24/10, bench TC, prisma a V).

COSA: src/vision/costruttori.py _candidate_anchors calcola i centroidi e fa l'ICP su TUTTI i bordi dell'immagine (DXFCompare.measured_contours): piastre del prisma, ombre, angoli neri della foto raddrizzata (borderValue=0) e bordo immagine. Centroide misurato (995,741) contro pezzo (706,1089) su sider_2_3: l'ICP parte lontano e converge sul fondo.

VERIFICATO (daitarn, worktree lavoro/daitarn-tmf-dxfcal 8ce7b48, px_per_mm 71,111, banda 0,1):

  • originale: MEVIS sider_2_1 1,6% punti in banda, sider_2_3 10,9%, PR165 sider_3_1 3,4%.
  • con l'immagine mascherata attorno al pezzo per la sola ricerca delle ancore + guardia overlay (TieVision-Core#337): MEVIS 93,3% / 90,7% (max 0,11 / 0,17 mm), PR165 sider_3_1 94,8% (max 0,22), sider_3_3 44,8% (da capire), doppia T col DXF 10x8 sbagliato 10% (scarto atteso).

FILE: src/vision/costruttori.py

  1. nuova funzione _maschera_pezzo(gray, polarity) -> np.ndarray: soglia Otsu (INV se dark), componenti connesse, la piu' grande che NON tocca il bordo immagine; dilatata di un margine (41x41 px nella prova; meglio in funzione della scala: ~0,3 mm * px_per_mm, minimo 15 px); fuori dalla maschera il pixel diventa sfondo (255 se dark, 0 se light). Nessun componente valido -> CostruttoreError("pezzo non trovato: nessun blob staccato dal bordo").
  2. _candidate_anchors(gray, dxf_path, px_per_mm) -> riceve anche polarity e lavora su _maschera_pezzo(gray, polarity) (centroide e ICP). La ricetta eseguita per giudicare le ancore resta sull'immagine intera (_run(frame, ...) invariato).
  3. _candidate_anchors: l'except Exception: continue nasconde il motivo; tenere il continue ma raccogliere il messaggio e metterlo nel CostruttoreError finale "ICP fallito" (diagnosi in campo).
  4. sider_3_3 a 44,8%: guardare se l'orientamento vincente e' sbagliato (4 angoli di partenza 0/90/180/270; il pezzo e' a ~35 gradi) o se e' l'esecuzione sull'immagine intera. Se servono piu' angoli di partenza (es. passo 45), aggiungerli. Riportare cosa si e' visto.

DIPENDE: TieVision-Core#337 (guardia in vs-dxf report.generate_overlay). Senza, con la maschera compare() solleva ValueError e TUTTI gli orientamenti cadono. Nel ramo TMF si puo' aspettare il bump del submodule; i test qui sotto girano dopo il bump.

TEST:

  • tests unitari esistenti di src/vision/tests: verdi.
  • nuovo test: immagine sintetica con pezzo scuro + rettangoli scuri attaccati al bordo + angolo nero -> _maschera_pezzo tiene solo il pezzo.
  • prova reale (non in CI, file locali su daitarn): D:/Sorgenti/AI-OS/data/tmp/menoncin-foto/raddr/.png con dxf/_profilo.dxf; atteso MEVIS sider_2_1/2_3 >= 90%, PR165 sider_3_1 >= 90%.

NON TOCCARE: scripts/calibrazione.py, scripts/camera_service.py, backend e frontend, il contratto della ricetta v2 (LocateBlob "pezzo" + CompareDxf "dxf").

Ricetta DXF compare dal campo (#83) non allinea il disegno sui pezzi veri di Menoncin (foto 24/10, bench TC, prisma a V). COSA: src/vision/costruttori.py `_candidate_anchors` calcola i centroidi e fa l'ICP su TUTTI i bordi dell'immagine (`DXFCompare.measured_contours`): piastre del prisma, ombre, angoli neri della foto raddrizzata (borderValue=0) e bordo immagine. Centroide misurato (995,741) contro pezzo (706,1089) su sider_2_3: l'ICP parte lontano e converge sul fondo. VERIFICATO (daitarn, worktree lavoro/daitarn-tmf-dxfcal 8ce7b48, px_per_mm 71,111, banda 0,1): - originale: MEVIS sider_2_1 1,6% punti in banda, sider_2_3 10,9%, PR165 sider_3_1 3,4%. - con l'immagine mascherata attorno al pezzo per la sola ricerca delle ancore + guardia overlay (TieVision-Core#337): MEVIS 93,3% / 90,7% (max 0,11 / 0,17 mm), PR165 sider_3_1 94,8% (max 0,22), sider_3_3 44,8% (da capire), doppia T col DXF 10x8 sbagliato 10% (scarto atteso). FILE: src/vision/costruttori.py 1. nuova funzione `_maschera_pezzo(gray, polarity) -> np.ndarray`: soglia Otsu (INV se dark), componenti connesse, la piu' grande che NON tocca il bordo immagine; dilatata di un margine (41x41 px nella prova; meglio in funzione della scala: ~0,3 mm * px_per_mm, minimo 15 px); fuori dalla maschera il pixel diventa sfondo (255 se dark, 0 se light). Nessun componente valido -> CostruttoreError("pezzo non trovato: nessun blob staccato dal bordo"). 2. `_candidate_anchors(gray, dxf_path, px_per_mm)` -> riceve anche `polarity` e lavora su `_maschera_pezzo(gray, polarity)` (centroide e ICP). La ricetta eseguita per giudicare le ancore resta sull'immagine intera (`_run(frame, ...)` invariato). 3. `_candidate_anchors`: l'`except Exception: continue` nasconde il motivo; tenere il continue ma raccogliere il messaggio e metterlo nel CostruttoreError finale "ICP fallito" (diagnosi in campo). 4. sider_3_3 a 44,8%: guardare se l'orientamento vincente e' sbagliato (4 angoli di partenza 0/90/180/270; il pezzo e' a ~35 gradi) o se e' l'esecuzione sull'immagine intera. Se servono piu' angoli di partenza (es. passo 45), aggiungerli. Riportare cosa si e' visto. DIPENDE: TieVision-Core#337 (guardia in vs-dxf report.generate_overlay). Senza, con la maschera compare() solleva ValueError e TUTTI gli orientamenti cadono. Nel ramo TMF si puo' aspettare il bump del submodule; i test qui sotto girano dopo il bump. TEST: - tests unitari esistenti di src/vision/tests: verdi. - nuovo test: immagine sintetica con pezzo scuro + rettangoli scuri attaccati al bordo + angolo nero -> `_maschera_pezzo` tiene solo il pezzo. - prova reale (non in CI, file locali su daitarn): D:/Sorgenti/AI-OS/data/tmp/menoncin-foto/raddr/*.png con dxf/*_profilo.dxf; atteso MEVIS sider_2_1/2_3 >= 90%, PR165 sider_3_1 >= 90%. NON TOCCARE: scripts/calibrazione.py, scripts/camera_service.py, backend e frontend, il contratto della ricetta v2 (LocateBlob "pezzo" + CompareDxf "dxf").
Adriano added the bug label 2026-10-24 11:51:01 +00:00
Author
Owner

Soluzione

src/vision/costruttori.py: _maschera_pezzo (Otsu, blob piu' grande staccato dal bordo, dilatato max(15 px, 0,3 mm), fuori = sfondo); _candidate_anchors fa centroide e ICP sull'immagine mascherata, la ricetta eseguita resta sull'immagine intera; l'errore 'ICP fallito' porta il motivo di ogni orientamento. 3 test nuovi in src/vision/tests/test_costruttori.py. Commit 11c7d2e (+ bump Core 88bba21 per TieVision-Core#337) su lavoro/daitarn-tmf-dxfcal. PROVA: pytest src/vision/tests src/vision_worker/tests vs-dxf -> 146 passed; foto reali Menoncin a 71,111 px/mm, banda 0,1: MEVIS 93,3/90,7/84,5/75,6%, PR165 94,8/92,1/96,0%, doppia T col DXF sbagliato 10% (scarto). Punto 4 (sider_3_3 35,5%) non dipende dalle ancore: aperta TieVision-Core#338.

**Soluzione** src/vision/costruttori.py: _maschera_pezzo (Otsu, blob piu' grande staccato dal bordo, dilatato max(15 px, 0,3 mm), fuori = sfondo); _candidate_anchors fa centroide e ICP sull'immagine mascherata, la ricetta eseguita resta sull'immagine intera; l'errore 'ICP fallito' porta il motivo di ogni orientamento. 3 test nuovi in src/vision/tests/test_costruttori.py. Commit 11c7d2e (+ bump Core 88bba21 per TieVision-Core#337) su lavoro/daitarn-tmf-dxfcal. PROVA: pytest src/vision/tests src/vision_worker/tests vs-dxf -> 146 passed; foto reali Menoncin a 71,111 px/mm, banda 0,1: MEVIS 93,3/90,7/84,5/75,6%, PR165 94,8/92,1/96,0%, doppia T col DXF sbagliato 10% (scarto). Punto 4 (sider_3_3 35,5%) non dipende dalle ancore: aperta TieVision-Core#338.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Adriano/TieMeasureFlow#86