<gh_stars>0
"""template.py - Template matching
"""
import numpy as np
from . import _template


def match_template(image, template, pad_input=False):
    """Match a template to a 2-D image using normalized correlation.

    The output is an array with values between -1.0 and 1.0, which correspond
    to the probability that the template is found at that position.

    Parameters
    ----------
    image : array_like
        2-D Image to process. 
    template : array_like
        Template to locate.
    pad_input : bool
        If True, pad `image` with image mean so that output is the same size as
        the image, and output values correspond to the template center.
        Otherwise, the output is an array with shape `(M - m + 1, N - n + 1)`
        for an `(M, N)` image and an `(m, n)` template, and matches correspond
        to origin (top-left corner) of the template.

    Returns
    -------
    output : ndarray
        Correlation results between -1.0 and 1.0. For an `(M, N)` image and an
        `(m, n)` template, the `output` is `(M - m + 1, N - n + 1)` when
        `pad_input = False` and `(M, N)` when `pad_input = True`.

    Examples
    --------
    >>> template = np.zeros((3, 3))
    >>> template[1, 1] = 1
    >>> print(template)
    [[ 0.  0.  0.]
     [ 0.  1.  0.]
     [ 0.  0.  0.]]
    >>> image = np.zeros((6, 6))
    >>> image[1, 1] = 1
    >>> image[4, 4] = -1
    >>> print(image)
    [[ 0.  0.  0.  0.  0.  0.]
     [ 0.  1.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0.  0.  0.]
     [ 0.  0.  0.  0. -1.  0.]
     [ 0.  0.  0.  0.  0.  0.]]
    >>> result = match_template(image, template)
    >>> print(np.round(result, 3))
    [[ 1.    -0.125  0.     0.   ]
     [-0.125 -0.125  0.     0.   ]
     [ 0.     0.     0.125  0.125]
     [ 0.     0.     0.125 -1.   ]]
    >>> result = match_template(image, template, pad_input=True)
    >>> print(np.round(result, 3))
    [[-0.125 -0.125 -0.125  0.     0.     0.   ]
     [-0.125  1.    -0.125  0.     0.     0.   ]
     [-0.125 -0.125 -0.125  0.     0.     0.   ]
     [ 0.     0.     0.     0.125  0.125  0.125]
     [ 0.     0.     0.     0.125 -1.     0.125]
     [ 0.     0.     0.     0.125  0.125  0.125]]
    """
    if np.any(np.less(image.shape, template.shape)):
        raise ValueError("Image must be larger than template.")
    image = np.ascontiguousarray(image, dtype=np.float32)
    template = np.ascontiguousarray(template, dtype=np.float32)

    if pad_input:
        pad_size = tuple(np.array(image.shape) + np.array(template.shape) - 1)
        pad_image = np.mean(image) * np.ones(pad_size, dtype=np.float32)
        h, w = image.shape
        i0, j0 = template.shape
        i0 /= 2
        j0 /= 2
        pad_image[i0:i0 + h, j0:j0 + w] = image
        image = pad_image
    result = _template.match_template(image, template)
    return result
