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
-
TM_SQDIFF: the calculated square is different. The smaller the calculated value is, the more relevant it is.
-
TM_CCORR: calculate the correlation. The larger the calculated value, the more relevant it is.
-
TM_CCOEFF: calculate the correlation coefficient. The larger the calculated value, the more correlation
-
TM_ SQDIFF_ Normalized: the calculated normalized square is different. The closer the calculated value is to 0, the more relevant it is.
-
TM_ CCORR_ Normalized: calculate the normalized correlation. The closer the calculated value is to 1, the more relevant it is.
-
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: