feat: 'Filtro falsi positivi' preset user-friendly (era verify_ncc)
Rinomina il parametro tecnico verify_threshold in un preset semantico che operatore/cliente capisce senza leggere docs: off -> 0.00 (tutti i match shape-based passano) leggero -> 0.20 (tollera illuminazione/riflessi) medio -> 0.35 (consigliato, default) forte -> 0.50 (massima selettivita, scarta mismatch intensita) UI: dropdown etichettato 'Filtro falsi positivi (verifica intensita colori)' accanto a precisione angolare. Override tecnico (numerico) resta in sezione Avanzate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+12
-4
@@ -210,6 +210,15 @@ PRECISION_ANGLE_STEP = {
|
|||||||
"preciso": 2.0,
|
"preciso": 2.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# "Filtro falsi positivi" = mapping semantico del verify NCC threshold.
|
||||||
|
# Un operatore sceglie il livello di rigore, non un numero astratto.
|
||||||
|
FILTRO_FP_MAP = {
|
||||||
|
"off": 0.0, # disabilitato: mantieni tutti i match shape-based
|
||||||
|
"leggero": 0.20, # tollera variazioni intensità/illuminazione forti
|
||||||
|
"medio": 0.35, # default bilanciato (consigliato)
|
||||||
|
"forte": 0.50, # scarta match con intensità molto diversa dal template
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class SimpleMatchParams(BaseModel):
|
class SimpleMatchParams(BaseModel):
|
||||||
model_id: str
|
model_id: str
|
||||||
@@ -219,7 +228,8 @@ class SimpleMatchParams(BaseModel):
|
|||||||
simmetria: str = "nessuna" # chiave SYMMETRY_TO_ANGLE_MAX
|
simmetria: str = "nessuna" # chiave SYMMETRY_TO_ANGLE_MAX
|
||||||
scala: str = "fissa" # chiave SCALE_PRESETS
|
scala: str = "fissa" # chiave SCALE_PRESETS
|
||||||
precisione: str = "normale" # chiave PRECISION_ANGLE_STEP
|
precisione: str = "normale" # chiave PRECISION_ANGLE_STEP
|
||||||
min_score: float = 0.70
|
filtro_fp: str = "medio" # chiave FILTRO_FP_MAP
|
||||||
|
min_score: float = 0.65
|
||||||
max_matches: int = 25
|
max_matches: int = 25
|
||||||
|
|
||||||
|
|
||||||
@@ -270,9 +280,7 @@ def _simple_to_technical(
|
|||||||
"min_score": p.min_score,
|
"min_score": p.min_score,
|
||||||
"max_matches": p.max_matches,
|
"max_matches": p.max_matches,
|
||||||
"nms_radius": 0,
|
"nms_radius": 0,
|
||||||
# Verify NCC più permissivo per match con variazione intensità
|
"verify_threshold": FILTRO_FP_MAP.get(p.filtro_fp, 0.35),
|
||||||
# (foro su sfondo variabile, parti di oggetto ecc.)
|
|
||||||
"verify_threshold": 0.25,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ function readUserParams() {
|
|||||||
simmetria: document.getElementById("p-simmetria").value,
|
simmetria: document.getElementById("p-simmetria").value,
|
||||||
scala: document.getElementById("p-scala").value,
|
scala: document.getElementById("p-scala").value,
|
||||||
precisione: document.getElementById("p-precisione").value,
|
precisione: document.getElementById("p-precisione").value,
|
||||||
|
filtro_fp: document.getElementById("p-filtro-fp").value,
|
||||||
min_score: parseFloat(document.getElementById("p-min-score").value),
|
min_score: parseFloat(document.getElementById("p-min-score").value),
|
||||||
max_matches: parseInt(document.getElementById("p-max-matches").value, 10),
|
max_matches: parseInt(document.getElementById("p-max-matches").value, 10),
|
||||||
};
|
};
|
||||||
@@ -238,6 +239,7 @@ async function doMatch() {
|
|||||||
const SCALE_MAP = {fissa:[1,1,0.1], mini:[0.9,1.1,0.05],
|
const SCALE_MAP = {fissa:[1,1,0.1], mini:[0.9,1.1,0.05],
|
||||||
medio:[0.75,1.25,0.05], max:[0.5,1.5,0.05]};
|
medio:[0.75,1.25,0.05], max:[0.5,1.5,0.05]};
|
||||||
const PREC_MAP = {veloce:10, normale:5, preciso:2};
|
const PREC_MAP = {veloce:10, normale:5, preciso:2};
|
||||||
|
const FP_MAP = {off:0, leggero:0.20, medio:0.35, forte:0.50};
|
||||||
const [smin, smax, sstep] = SCALE_MAP[user.scala];
|
const [smin, smax, sstep] = SCALE_MAP[user.scala];
|
||||||
body = {
|
body = {
|
||||||
model_id: state.model.id, scene_id: state.scene.id, roi: state.roi,
|
model_id: state.model.id, scene_id: state.scene.id, roi: state.roi,
|
||||||
@@ -250,7 +252,7 @@ async function doMatch() {
|
|||||||
strong_grad: adv.strong_grad ?? 60,
|
strong_grad: adv.strong_grad ?? 60,
|
||||||
spread_radius: adv.spread_radius ?? 5,
|
spread_radius: adv.spread_radius ?? 5,
|
||||||
pyramid_levels: adv.pyramid_levels ?? 3,
|
pyramid_levels: adv.pyramid_levels ?? 3,
|
||||||
verify_threshold: adv.verify_threshold ?? 0.4,
|
verify_threshold: adv.verify_threshold ?? (FP_MAP[user.filtro_fp] ?? 0.35),
|
||||||
nms_radius: adv.nms_radius ?? 0,
|
nms_radius: adv.nms_radius ?? 0,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -81,6 +81,18 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="field">
|
||||||
|
<label>Filtro falsi positivi
|
||||||
|
<span class="hint">(verifica intensità colori)</span>
|
||||||
|
</label>
|
||||||
|
<select id="p-filtro-fp">
|
||||||
|
<option value="off">Disattivato (massimo recall)</option>
|
||||||
|
<option value="leggero">Leggero (tollera illuminazione)</option>
|
||||||
|
<option value="medio" selected>Medio (consigliato)</option>
|
||||||
|
<option value="forte">Forte (massima selettività)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Score minimo <span id="v-score">0.65</span>
|
<label>Score minimo <span id="v-score">0.65</span>
|
||||||
<span class="hint">(più basso = più match anche incerti)</span>
|
<span class="hint">(più basso = più match anche incerti)</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user