Compare commits

..

1 Commits

Author SHA1 Message Date
Adriano 746d1668c6 feat: NCC verify lazy con skip per shape-score alto
ncc_skip_above (default 0.85): se lo score shape e gia molto alto,
salta la verifica NCC (costosa: warp + corr per ogni match). I match
borderline 0.6-0.85 vengono comunque verificati.

Comportamento Halcon-style: NCC come tie-breaker per casi ambigui,
non come gate generalizzato. Su scene con molti match netti riduce
sensibilmente il costo della fase post-NMS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 15:28:24 +02:00
2 changed files with 8 additions and 15 deletions
+2 -14
View File
@@ -246,22 +246,10 @@ def score_bitmap_rescored(
return np.maximum(0.0, out).astype(np.float32)
_HAS_NP_BITCOUNT = hasattr(np, "bitwise_count")
def popcount_density(spread: np.ndarray) -> np.ndarray:
"""Conta bit set per pixel.
Order:
1) Numba JIT parallel (preferito: piu veloce su 1080p, 0.5ms vs 1.6ms)
2) numpy.bitwise_count (NumPy 2.0+, SIMD ma single-thread)
3) Fallback numpy bit-shift puro
"""
spread_c = np.ascontiguousarray(spread, dtype=np.uint8)
if HAS_NUMBA:
return _jit_popcount_density(spread_c)
if _HAS_NP_BITCOUNT:
return np.bitwise_count(spread_c).astype(np.float32, copy=False)
return _jit_popcount_density(np.ascontiguousarray(spread, dtype=np.uint8))
# Fallback
H, W = spread.shape
out = np.zeros((H, W), dtype=np.float32)
for b in range(8):
+6 -1
View File
@@ -572,6 +572,7 @@ class LineShapeMatcher:
subpixel: bool = True,
verify_ncc: bool = True,
verify_threshold: float = 0.4,
ncc_skip_above: float = 0.85,
coarse_angle_factor: int = 2,
scale_penalty: float = 0.0,
) -> list[Match]:
@@ -805,7 +806,11 @@ class LineShapeMatcher:
search_radius=self.angle_step_deg / 2.0,
original_score=score,
)
if verify_ncc:
# NCC verify lazy (Halcon-style): skip se shape-score gia molto
# alto (probabilita falso positivo trascurabile). NCC e l'op
# piu costosa per match (warp + corr), quindi vale la pena
# saltarlo quando il gradiente shape e gia conclusivo.
if verify_ncc and float(score_f) < ncc_skip_above:
ncc = self._verify_ncc(gray0, cx_f, cy_f, ang_f, var.scale)
if ncc < verify_threshold:
continue