Coverage for src/dictk/core.py: 100%
12 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-24 22:28 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-07-24 22:28 +0000
1"""Core numerical primitives for digital image correlation."""
3import numpy as np
6def zero_normalized_cross_correlation(a: np.ndarray, b: np.ndarray) -> float:
7 """Compute the zero-normalized cross-correlation (ZNCC) between two arrays.
9 ZNCC is a similarity metric commonly used as the matching criterion in
10 digital image correlation (DIC) template matching: it compares two
11 equal-shaped patches (e.g. image subsets) while being invariant to
12 linear changes in brightness and contrast. A return value of ``1.0``
13 indicates a perfect match, ``-1.0`` a perfect inverse match, and ``0.0``
14 no correlation.
16 Args:
17 a: First array (e.g. a reference image subset).
18 b: Second array, same shape as ``a`` (e.g. a deformed image subset).
20 Returns:
21 The ZNCC score in the range ``[-1.0, 1.0]``.
23 Raises:
24 ValueError: If ``a`` and ``b`` do not have the same shape.
25 """
26 a = np.asarray(a, dtype=np.float64)
27 b = np.asarray(b, dtype=np.float64)
29 if a.shape != b.shape:
30 raise ValueError(f"shape mismatch: a.shape={a.shape}, b.shape={b.shape}")
32 a_centered = a - a.mean()
33 b_centered = b - b.mean()
35 denominator = np.sqrt(np.sum(a_centered**2) * np.sum(b_centered**2))
36 if denominator == 0:
37 return 0.0
39 return float(np.sum(a_centered * b_centered) / denominator)