From 37c645984f8a4f1287d973364c32397660d9066a Mon Sep 17 00:00:00 2001 From: AdrianoDev Date: Mon, 4 May 2026 23:10:07 +0200 Subject: [PATCH] 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) --- pm2d/web/server.py | 4 +++- pm2d/web/static/app.js | 48 ++++++++++++++++++++++++++++++++++++++ pm2d/web/static/index.html | 4 ++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/pm2d/web/server.py b/pm2d/web/server.py index 27460ab..1532519 100644 --- a/pm2d/web/server.py +++ b/pm2d/web/server.py @@ -607,7 +607,9 @@ def tune(p: TuneParams): x, y, w, h = p.roi roi_img = model[y:y + h, x:x + w] t = auto_tune(roi_img) - return {k: v for k, v in t.items() if not k.startswith("_")} + # Esponi parametri tecnici + meta diagnostica (_self_score, _validation, + # _symmetry_order, _orient_entropy) per feedback UI. + return t # --- V: Save/Load ricette pre-trained --- diff --git a/pm2d/web/static/app.js b/pm2d/web/static/app.js index 03db2a0..c4b61fa 100644 --- a/pm2d/web/static/app.js +++ b/pm2d/web/static/app.js @@ -400,6 +400,53 @@ function setStatus(s) { } // ---------- Init ---------- +// ---------- Auto-tune (Halcon-style) ---------- +async function doAutoTune() { + if (!state.model || !state.roi) { + alert("Seleziona modello e disegna ROI prima di Auto-tune."); + return; + } + const status = document.getElementById("status"); + status.textContent = "Analisi ROI in corso..."; + try { + const r = await fetch("/auto_tune", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + model_id: state.model.id, + roi: state.roi, + }), + }); + if (!r.ok) throw new Error(await r.text()); + const t = await r.json(); + // Applica ai campi avanzati (override automatico) + for (const [key] of ADV_PARAMS) { + const el = document.getElementById(`adv-${key}`); + if (el && t[key] !== undefined) el.value = String(t[key]); + } + // Espandi la sezione Avanzate per mostrare i valori applicati + const advDetails = document.querySelector("#col-params details:last-of-type"); + if (advDetails) advDetails.open = true; + // Feedback diagnostico + const lines = [ + `weak/strong: ${t.weak_grad} / ${t.strong_grad}`, + `feature: ${t.num_features}, piramide: ${t.pyramid_levels}`, + `angle: [${t.angle_min}..${t.angle_max}]@${t.angle_step}°`, + ]; + if (t._symmetry_order > 1) { + lines.push(`simmetria rotaz. ${t._symmetry_order}x (conf ${t._symmetry_conf})`); + } + if (t._self_score !== undefined) { + lines.push(`self-validation: ${t._validation}`); + } + status.textContent = `Auto-tune OK — ${lines[0]}`; + alert("Auto-tune completato:\n\n" + lines.join("\n")); + } catch (e) { + status.textContent = `Auto-tune errore: ${e.message}`; + alert(`Errore auto-tune: ${e.message}`); + } +} + // ---------- V: Save recipe ---------- async function saveRecipe() { if (!state.model || !state.roi) { @@ -465,6 +512,7 @@ window.addEventListener("DOMContentLoaded", async () => { e.target.value = ""; // consente re-upload stesso file }); document.getElementById("btn-match").addEventListener("click", doMatch); + document.getElementById("btn-autotune").addEventListener("click", doAutoTune); document.getElementById("btn-save-recipe").addEventListener("click", saveRecipe); const slider = document.getElementById("p-min-score"); diff --git a/pm2d/web/static/index.html b/pm2d/web/static/index.html index 55679bf..43532dd 100644 --- a/pm2d/web/static/index.html +++ b/pm2d/web/static/index.html @@ -26,6 +26,10 @@
+