Single Template Matching Principle
Template matching is a method of searching and finding the location of a template image within a larger image. OpenCV provides a function cv.matchTemplate() for this purpose. It just slides the template image onto the input image (as in 2D convolution) and compares the template and input image patches under the template image. Several comparison methods are implemented in OpenCV. It returns a grayscale image where each pixel represents how well that pixel's neighborhood matches the template.
If the size of the input image is (WxH) and the size of the template image is (wxh), then the size of the output image is (W-w+1, H-h+1). After getting the result, you can use the cv.minMaxLoc() function to find the location of the maximum/minimum value. Take it as the upper left corner of the rectangle, and take (w,h) as the width and height of the rectangle. This rectangle is the area of the template.
function
matchTemplate(image, templ, method[, result[, mask]])
minMaxLoc(src[, mask])
Parameters:
image : the input image
templ : the input template, which must be no larger than the source image and have the same data type.
method: Specifies the parameters of the comparison method
Others: https://docs.opencv.org/4.x/df/dfb/group__imgproc__object.html#gga3a7850640f1fe1f58fe91a2d7583695dac5babb7dfda59544e3e31ea928f8cb16
Code example:
import matplotlib.pyplot as plt
import numpy as np
import cv2
img = cv2.imread("./lena.jpg",cv2.IMREAD_COLOR)
img = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
tampalet = cv2.imread("./lena-tampalet.jpg",cv2.IMREAD_COLOR)
tampalet = cv2.cvtColor(tampalet,cv2.COLOR_RGB2GRAY)
print(tampalet.shape)
h,w = tampalet.shape
print((w,h))
cv2.imshow("lena",img)
cv2.imshow("img_tamp",tampalet)
tampalets = ['cv2.TM_SQDIFF','cv2.TM_CCORR','cv2.TM_CCOEFF','cv2.TM_SQDIFF_NORMED','cv2.TM_CCORR_NORMED','cv2.TM_CCOEFF_NORMED']
for meth in tampalets:
img2 = img.copy()
method = eval(meth)
res = cv2.matchTemplate(img,tampalet,method)
min_val,max_val,min_loc,max_loc = cv2.minMaxLoc(res)
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(img2,top_left,bottom_right,255,2)
plt.subplot(121),plt.imshow(res,cmap='gray')
plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(img2,cmap='gray')
plt.xticks([]),plt.yticks([])
plt.suptitle(meth)
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
result:
Original image:
Template:
Matching result display:
Multiple Object Template Matching
Searching for an object with multiple occurrences, cv.minMaxLoc() won't give you all the locations. In this case, we will use threshold segmentation. So in this example we will use a screenshot of the famous game Mario, where we will find coins.
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img_rgb = cv.imread('mario.png')
img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
template = cv.imread('mario_coin.png',0)
w, h = template.shape[::-1]
res = cv.matchTemplate(img_gray,template,cv.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
cv.imwrite('res.png',img_rgb)