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

1"""Core numerical primitives for digital image correlation.""" 

2 

3import numpy as np 

4 

5 

6def zero_normalized_cross_correlation(a: np.ndarray, b: np.ndarray) -> float: 

7 """Compute the zero-normalized cross-correlation (ZNCC) between two arrays. 

8 

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. 

15 

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). 

19 

20 Returns: 

21 The ZNCC score in the range ``[-1.0, 1.0]``. 

22 

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) 

28 

29 if a.shape != b.shape: 

30 raise ValueError(f"shape mismatch: a.shape={a.shape}, b.shape={b.shape}") 

31 

32 a_centered = a - a.mean() 

33 b_centered = b - b.mean() 

34 

35 denominator = np.sqrt(np.sum(a_centered**2) * np.sum(b_centered**2)) 

36 if denominator == 0: 

37 return 0.0 

38 

39 return float(np.sum(a_centered * b_centered) / denominator)