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