OpenCV template matching

Posted by Amman-DJ on Wed, 22 Sep 2021 19:38:36 +0200

Introduction to the concept of template matching

  • The principle of template matching and convolution is very similar. The template slides from the origin on the original image to calculate the difference between the template and (where the image is covered by the template). There are six calculation methods for this difference in opencv, and then the results of each calculation are put into a matrix and output as the results. If the original graph is AXB size and the template is AXB size, the matrix of the output result is (A-a+1)x(B-b+1).
  • For example, we perform template matching on Lena's face, as shown in the following figure:

#Related code
img = cv2.imread('lena.jpg', 0)
template = cv2.imread('face.jpg', 0)
h, w = template.shape[:2] 
#Output drawing size
img.shape
(263, 263)
template.shape
(110, 85)

Several common algorithms of template matching

  1. TM_SQDIFF: the calculated square is different. The smaller the calculated value is, the more relevant it is.

  2. TM_CCORR: calculate the correlation. The larger the calculated value, the more relevant it is.

  3. TM_CCOEFF: calculate the correlation coefficient. The larger the calculated value, the more correlation

  4. TM_ SQDIFF_ Normalized: the calculated normalized square is different. The closer the calculated value is to 0, the more relevant it is.

  5. TM_ CCORR_ Normalized: calculate the normalized correlation. The closer the calculated value is to 1, the more relevant it is.

  6. TM_ CCOEFF_ Normalized: calculate the normalized correlation coefficient. The closer the calculated value is to 1, the more relevant it is.

  • Next to the small demo in the previous section, we first specify a list of method s, and then use the template matching function.
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
           'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
res = cv2.matchTemplate(img, template, cv2.TM_SQDIFF)
res.shape
(154, 179)
  • Because the matching process through the sliding window is very troublesome, OpenCV provides the cv2.minMaxLoc() function here. Input the calculated matrix size and directly return four values. The code is as follows:
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
#minimum value
min_val
39168.0
#Maximum
max_val
74403584.0
#Minimum coordinate position
min_loc
(107, 89)
#Maximum coordinate position
max_loc
(159, 62)
  • The usage of these values depends on the template selected between, for example, cv2.tm_ The sqdiff method is based on the previous definition on the official website: the smaller the value, the more relevant it is. So we finally use min_loc this value.
  • Conclusion: when we do template matching, we try to use the normalization method. For example: cv2.TM_SQDIFF_NORMED,cv2.TM_CCOEFF_NORMED et al.

Matching effect display

Match an object

  • Relevant code display:
import cv2 #The format read by opencv is BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib is RGB
%matplotlib inline 
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:
    img2 = img.copy()

    # True value of matching method
    method = eval(meth)
    print (method)
    res = cv2.matchTemplate(img, template, method)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

    # If it is square difference matching TM_SQDIFF or normalized square difference matching TM_SQDIFF_ Normalized, take the minimum value
    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)

    # Draw rectangle
    cv2.rectangle(img2, top_left, bottom_right, 255, 2)

    plt.subplot(121), plt.imshow(res, cmap='gray')
    plt.xticks([]), plt.yticks([])  # Hide axes
    plt.subplot(122), plt.imshow(img2, cmap='gray')
    plt.xticks([]), plt.yticks([])
    plt.suptitle(meth)
    plt.show()
  • Display results


  • Conclusion: for those with normalization, the matching effect is quite good.

Match multiple objects

  • Related code display
#This is a code block matching Mario gold coins
img_rgb = cv2.imread('mario.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('mario_coin.jpg', 0)
h, w = template.shape[:2]

res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
#You need to set a threshold when matching multiple objects
threshold = 0.8
# Take the coordinates with matching degree greater than% 80 and find the coordinates in np.where
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):  # *The number indicates an optional parameter
    bottom_right = (pt[0] + w, pt[1] + h)
    cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)

cv2.imshow('img_rgb', img_rgb)
cv2.waitKey(0)
  • Effect display diagram:

Topics: Python OpenCV