首页 > 解决方案 > Check if a template exists using match_template from scikit-image

问题描述

I'm trying to use the match_template method from the scikit-image library to check if a template exists inside an image and get its X and Y positions. I'm using the scikit-image template matching example.

My code looks like this:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import numpy as np
from skimage import io
from skimage.color import rgb2gray
from skimage.feature import match_template


def exists(image, template):
    """Perform a template match and returns the X and Y positions.

    Args:
        image (str): path to the full image.
        template (str): path to the template image.

    Returns:
        If there is a match, return the X and Y positions.
        If there is not match, return None.
    """

    image = io.imread(image, as_gray=True)
    template = io.imread(template, as_gray=True)

    result = match_template(image, template, pad_input=True)

    return np.unravel_index(np.argmax(result), result.shape)[::-1]

    # unreachable
    return None

It is performing the template match correctly when it exists in the image, but when the template doesn't exist it gives me wrong X and Y positions.

How can I check if the template doesn't exist and return None in this case?

标签: pythonscikit-imagetemplate-matching

解决方案


I don't know enough about the output of match_template to give you a definitive answer, but the critical thing is that the function always returns just the correlation image:

Returns
-------
output : array
    Response image with correlation coefficients.

Therefore, to determine that you haven't found a template match, you have to determine that the max of output is below some threshold. I don't know what a good threshold is. In general, I think it will vary depending on the size of your template and on how much noise/variation you want to allow. My suggestion is that you run match_template on a few positive examples (containing the template, with varying amounts of noise) and a few negative ones (without), and plot the two distributions to choose a threshold. Then you can add:

def exists(image, template, threshold):
    ...
    max_corr = np.max(result)
    if max_corr > threshold:
        return np.unravel_index(np.argmax(result), result.shape)[::-1]
    else:
        return None

推荐阅读