From 5002515b41e68a440a2e5898ec7abc9218d2c84c Mon Sep 17 00:00:00 2001 From: AdrianoDev Date: Tue, 5 May 2026 12:13:07 +0200 Subject: [PATCH] fix: rimuove edge spuri sui bordi template warpato (apparivano come ROI) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: per ogni match l'overlay edge del modello includeva anche il PERIMETRO del template warpato (transizione bordo nero borderValue=0 → scena = forte gradient artefatto). Con N match si vedevano N rettangoli verdi attorno ai pezzi, simili a "ROI ripetute". Fix: - Warpa anche _train_mask alla pose - Erode di (2*spread_radius+1) per scartare la fascia di transizione bordo che produce gradient spurio - Maschera edge_mask con warped_mask: solo edge interni al pezzo vengono visualizzati Risultato: overlay edge pulito che mostra solo i veri edge del modello allineati al pezzo trovato, niente cornici fasulle. Co-Authored-By: Claude Opus 4.7 (1M context) --- pm2d/web/server.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pm2d/web/server.py b/pm2d/web/server.py index 0a1e0de..94b0db4 100644 --- a/pm2d/web/server.py +++ b/pm2d/web/server.py @@ -161,7 +161,10 @@ def _draw_matches(scene: np.ndarray, matches: list[Match], cx, cy = int(round(m.cx)), int(round(m.cy)) # Overlay edge del modello orientato (richiesta utente): # warpa template alla pose, applica hysteresis identica al matcher, - # disegna pixel edge come overlay verde tenue. + # disegna pixel edge come overlay verde tenue. Maschera col + # _train_mask warpato + erode per rimuovere edge sui BORDI del + # rettangolo template (transizione bordo nero → scena = falso edge + # che appariva come "ROI" attorno a ogni match). if template_gray is not None and matcher is not None: t = template_gray th, tw = t.shape @@ -172,11 +175,23 @@ def _draw_matches(scene: np.ndarray, matches: list[Match], warped_gray = cv2.warpAffine( t, M, (W_scene, H_scene), flags=cv2.INTER_LINEAR, borderValue=0) + # Maschera: train_mask se disponibile, altrimenti rettangolo pieno + mask_src = (matcher._train_mask if matcher._train_mask is not None + else np.full((th, tw), 255, dtype=np.uint8)) + warped_mask = cv2.warpAffine( + mask_src, M, (W_scene, H_scene), + flags=cv2.INTER_NEAREST, borderValue=0) + # Erode di spread_radius per scartare la fascia di transizione + # bordo che produce gradient spurio + er_k = max(3, 2 * matcher.spread_radius + 1) + kernel_er = np.ones((er_k, er_k), np.uint8) + warped_mask = cv2.erode(warped_mask, kernel_er) mag, _ = matcher._gradient(warped_gray) if matcher.weak_grad < matcher.strong_grad: edge_mask = matcher._hysteresis_mask(mag) else: edge_mask = mag >= matcher.strong_grad + edge_mask = edge_mask & (warped_mask > 0) if edge_mask.any(): edge_overlay = np.zeros_like(out) edge_overlay[edge_mask] = (0, 220, 0) # verde brillante