Use template matching to find the object in the image
Template matching
Template matching is used to find small map in the big picture, ie find the location of another one template image in an image:
OpenCV with cv.matchTemplate () to achieve template matching.
Template matching principle is very simple, is constantly moving in the template image to compare the original , there are six different comparison method, the details may refer to: TemplateMatchModes
1. squared differences match CV_TM_SQDIFF: with the square of the difference between the two to match the best matching value 0
2. normalized square difference matching CV_TM_SQDIFF_NORMED
3. correlation matching CV_TM_CCORR: matching product of the two, the greater the value the better the degree of match indicates that
4 normalized correlation matching CV_TM_CCORR_NORMED
5. the correlation coefficient match CV_TM_CCOEFF: with the correlation coefficient match, 1 indicates a perfect match and -1 for worst match
6. the normalized correlation coefficient match CV_TM_CCOEFF_NORMED
normalized to unity means that the value of 0 to 1, the code of these methods may Comparative view the source code at. Template matching is achieved convolution: Suppose original size W × H, template FIG size w × h, then generates FIG size (W-w + 1) × (H-h + 1), FIG generate each pixel value represents the degree of matching with the original template.
Experiment: source image matches the template image
Source image:
a template image:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1.模板匹配
img = cv.imread('lena.jpg', 0)
template = cv.imread('face.jpg', 0)
h, w = template.shape[:2] # rows->h, cols->w
# 6种匹配方法
methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR',
'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']
for meth in methods:
img2 = img.copy()
# 匹配方法的真值
method = eval(meth)
res = cv.matchTemplate(img, template, method)
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
# 如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED,取最小值
if method in [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
# 画矩形
cv.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()
Experimental results
Matching a plurality of objects
We are looking for the biggest match in front of the point, it can only match once. We can set up a match threshold to match many times:
Experiment: match image coins
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 2.匹配多个物体
img_rgb = cv.imread('mario.jpg')
img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
template = cv.imread('mario_coin.jpg', 0)
h, w = template.shape[:2]
res = cv.matchTemplate(img_gray, template, cv.TM_CCOEFF_NORMED)
threshold = 0.8
# 取匹配程度大于%80的坐标
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]): # *号表示可选参数
bottom_right = (pt[0] + w, pt[1] + h)
cv.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
cv.imshow('img_rgb', img_rgb)
cv.waitKey(0)
cv.destroyAllWindows()
Code is difficult to explain
Step 3. There are several important knowledge of Python / Numpy of:
x = np.arange(9.).reshape(3, 3)
print(np.where(x > 5))
# 结果:(array([2, 2, 2]), array([0, 1, 2]))
zip () function, powerful hard to explain, give a simple example to know:
x = [1, 2, 3]
y = [4, 5, 6]
print(list(zip(x, y))) # [(1, 4), (2, 5), (3, 6)]