Showing posts with label scipy. Show all posts
Showing posts with label scipy. Show all posts

Friday, September 29, 2017

Matlab normxcorr2 implemented in python

For some reason there is no direct implementation of normxcorr2 from Matlab or Octave in numpy or scipy. This is a near exact normxcorr2 taken from Octave's implementation using numpy and scipy's fftconvolve.

# Based on Octave implementation by Benjamin Eltzner 

import numpy as np
from scipy.signal import fftconvolve


def normxcorr2(template, image, mode="full"):
    # If this happens, it is probably a mistake    
    if np.ndim(template) > np.ndim(image) or \
            len([i for i in range(np.ndim(template))
                 if template.shape[i] > image.shape[i]]) > 0:
        print("normxcorr2: TEMPLATE larger than IMG. Arguments may be swapped.")

    template = template - np.mean(template)
    image = image - np.mean(image)

    a1 = np.ones(template.shape)
    ar = np.flipud(np.fliplr(template))

    out = fftconvolve(image, ar.conj(), mode=mode)
    image = fftconvolve(np.square(image), a1, mode=mode) - \
            np.square(fftconvolve(image, a1, mode=mode)) / (np.prod(template.shape))

    # Remove small machine precision errors after subtraction
    image[np.where(image < 0)] = 0
    template = np.sum(np.square(template))
    out = out / np.sqrt(image * template)

    out[np.where(np.logical_not(np.isfinite(out)))] = 0
    return out

Using fftconvolve as it is significantly faster than convolve2d or correlate2d. Also allows for N-dimensions.
Python file available on GitHub: normxcorr2-python