opencv25: template matching

Keywords: Python OpenCV

target

In this chapter, you will learn

  • Find objects in images using template matching
  • Function: cv2.matchTemplate(), cv2.minMaxLoc()

theory

Template matching is a method used to search and find the location of template image in large image. To this end, OpenCV implements a function cv2.matchTemplate().
It just slides the template image onto the input image (just like in 2D convolution), and then compares the puzzle of the template and the input image under the template image.
Several comparison methods are implemented in OpenCV. It returns a grayscale image, where each pixel represents the degree to which the pixel's neighborhood matches the template.

If the size of the input image is (WXH) and the size of the template image is (WXH), the size of the output image will be (W-w+1, H-h+1). Once you get the result, you can use the cv2.minMaxLoc() function to find out where the maximum / minimum value is. Take it as the upper left corner of the rectangle, and take (w, h) as the width and height of the rectangle, which is the area of the template.

be careful
If cv2.tm is used_ As a comparison method, sqdiff is the minimum value to provide the best match.

Template matching in OpenCV

As an example, you will search for Messi's face in his photos. Therefore, a template is created as follows:

All comparison methods will be tried so that you can see their results:

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('messi.png', 0)
img2 = img.copy()

template = cv2.imread('template.png', 0)
w, h = template.shape[::-1]

# All the 6 methods for comparison in a list
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED',
    'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED',
    'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']

for meth in methods:
    img = img2.copy()
    method = eval(meth)
    # apply template matching
    res = cv2.matchTemplate(img, template, method)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    
    # if the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc
    
    bottom_right = (top_left[0]+w, top_left[1]+h)
    cv2.rectangle(img, top_left, bottom_right, 255, 2)
    plt.subplot(121),plt.imshow(res,cmap = 'gray')
    plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
    plt.subplot(122),plt.imshow(img,cmap = 'gray')
    plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
    plt.suptitle(meth)
    plt.show()

View the following results:

  • cv2.TM_CCOEFF

  • cv2.TM_CCOEFF_NORMED

  • cv2.TM_CCORR

  • cv2.TM_CCORR_NORMED

  • cv2.TM_SQDIFF

  • cv2.TM_SQDIFF_NORMED

As you can see, using cv2.TM_CCORR series and cv2.tm_ SQDIFF_ The result of normalized is not ideal

Multi object template matching

In the previous section, we searched for Messi's face in the image, which appears only once in the image. Assuming you are searching for an object with multiple occurrences, cv2.minMaxLoc() does not provide all locations. In this case, thresholding is used. Therefore, in this example, we will use a screenshot of the famous game Mario and find a coin in it.

# Match multiple objects
img_bgr = cv2.imread('mario.png')
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)  # plt.imshow different from cv2.imshow
img_copy = img_rgb.copy()
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)

template = cv2.imread('mario_coin.png', 0)
w, h = template.shape[::-1]

res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
    cv2.rectangle(img_rgb, pt, (pt[0]+w, pt[1]+h), (0,0,255), 2)

plt.subplot(121)
plt.imshow(img_copy)
plt.title('origin')
plt.xticks([])
plt.yticks([])


plt.subplot(122)
plt.imshow(img_rgb)
plt.title('match res')
plt.xticks([])
plt.yticks([])

plt.show()

result:

Additional resources

Posted by avalonindigo on Wed, 03 Nov 2021 17:16:11 -0700