From 88f80a2cad45fd49376e7f3171b6bbcc44ceb78b Mon Sep 17 00:00:00 2001 From: AdrianoDev Date: Tue, 5 May 2026 12:38:47 +0200 Subject: [PATCH] fix: refine angolo piu' veloce + edge overlay ciano (no clash con asse Y) Bug visibili dallo screenshot: 1. Rallentamento sostanziale: il fix precedente aggiungeva 16 iter golden (era 8) + 3 chiamate parabolic fit = ~19 _score_at_angle vs 11 prima. 2. Asse Y dell'UCS invisibile sul match: edge overlay era verde brillante (0,220,0) e si sovrapponeva esattamente al verde dell'asse Y dell'UCS. 3. Angolo non corretto: il parabolic fit finale era instabile su template simmetrici (multiple local max ravvicinati lo facevano divergere fuori dal vero picco trovato dal golden). Fix: - _refine_angle: 10 iter golden con tol 0.05 (compromesso tra precisione e velocita'). Rimosso parabolic fit finale instabile. search_radius resta a step pieno (utile per recuperare estremi del bin). - Edge overlay color: ciano (BGR 255,200,0) invece di verde brillante. L'asse Y verde dell'UCS ora ben visibile sopra l'overlay. Co-Authored-By: Claude Opus 4.7 (1M context) --- pm2d/line_matcher.py | 27 ++++++--------------------- pm2d/web/server.py | 4 +++- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/pm2d/line_matcher.py b/pm2d/line_matcher.py index 360a82d..87c108f 100644 --- a/pm2d/line_matcher.py +++ b/pm2d/line_matcher.py @@ -1042,11 +1042,12 @@ class LineShapeMatcher: # Score all'origine come riferimento (ang offset 0) s0, cx0_s, cy0_s = _score_at_angle(0.0) best = (angle_deg, s0, cx0_s, cy0_s) - # Precisione angolare: tol piu' stretto + piu' iterazioni golden. - # 16 iter golden coprono ~1e-3 della search_radius -> precisione - # ~0.005 deg per step=10 deg. - tol = 0.02 - for _ in range(16): + # Precisione angolare: 10 iter golden con tol 0.05 deg. + # Compromesso speed/accuracy: il parabolic fit aggiuntivo era + # instabile su score map non-smooth (template simmetrici producono + # multipli local max ravvicinati che lo facevano divergere). + tol = 0.05 + for _ in range(10): if s1 > best[1]: best = (angle_deg + x1, s1, cx1, cy1) if s2 > best[1]: @@ -1063,22 +1064,6 @@ class LineShapeMatcher: x1 = x2; s1 = s2; cx1 = cx2; cy1 = cy2 x2 = a_lo + _GOLDEN * (a_hi - a_lo) s2, cx2, cy2 = _score_at_angle(x2) - # Parabolic fit finale sui 3 punti vicini al best per refinement - # sub-step ulteriore (precisione <0.01 deg quando lo score map e' - # smooth attorno al picco). - best_off = best[0] - angle_deg - delta = max(0.05, abs(a_hi - a_lo) * 0.5) - sm, _, _ = _score_at_angle(best_off - delta) - sp, _, _ = _score_at_angle(best_off + delta) - # Vertice parabola su 3 punti (sm, sb, sp) a (-delta, 0, +delta) - denom = sm - 2 * best[1] + sp - if abs(denom) > 1e-9: - shift = 0.5 * (sm - sp) / denom * delta - shift = max(-delta, min(delta, shift)) - new_off = best_off + shift - sn, cxn, cyn = _score_at_angle(new_off) - if sn >= best[1]: - return (angle_deg + new_off, sn, cxn, cyn) return best def _get_view_template( diff --git a/pm2d/web/server.py b/pm2d/web/server.py index 94b0db4..8fdaf68 100644 --- a/pm2d/web/server.py +++ b/pm2d/web/server.py @@ -194,7 +194,9 @@ def _draw_matches(scene: np.ndarray, matches: list[Match], 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 + # Ciano (cambiato da verde): non collide col verde dell'asse + # Y dell'UCS che altrimenti scompariva nell'overlay edge. + edge_overlay[edge_mask] = (255, 200, 0) # ciano (BGR) out = cv2.addWeighted(out, 1.0, edge_overlay, 0.6, 0) L = max(20, int(L_base * m.scale)) # X axis = rotazione di (1, 0) con cv2 matrix → (cos, -sin)