前言
模板匹配是一种在较大的图像中搜索和查找模板图像位置的方法。OpenCV带有一个函数cv.matchTemplate()用于此目的。它只是简单地将模板图像放在输入图像上(就像在2D卷积中那样),并在模板图像下对输入图像的模板和补丁进行比较。在OpenCV中实现了几种比较方法。它返回一个灰度图像,每个像素表示该像素区域与模板的匹配程度。
如果输入图像大小是(W x H)、模板图像大小是(w x h),输出的图像会有大小(W-w+1,H-h+1)。一旦得到了结果,就可以使用cv.minMaxLoc()函数来查找最大值/最小值的位置。将它作为矩形的左上角,并将(w,h)作为矩形的宽度和高度。这个矩形是你的模板区域。
如果你在使用cv.TM_SQDIFF作为比较方法,最小值提供了最佳匹配。(引自:python OpenCV学习笔记(二十六):模板匹配
正文
代码
import cv2 as cv
import numpy as np
# 模板匹配,就是在整个图像区域发现与给定子图像匹配的小块区域,
# 需要模板图像T和待检测图像-源图像S
# 工作方法:在待检测的图像上,从左到右,从上倒下计算模板图像与重叠子图像匹配度,
# 匹配度越大,两者相同的可能性越大。
def template_demo():
tpl = cv.imread("../images/plane3.jpg")
target = cv.imread("../images/plane.jpg")
cv.imshow("template",tpl)
cv.imshow("target",target)
methods = [cv.TM_SQDIFF_NORMED,cv.TM_CCORR_NORMED,cv.TM_CCOEFF_NORMED]
th,tw = tpl.shape[:2]
for md in methods:
print(md)
result = cv.matchTemplate(target,tpl,md)
min_val,max_val,min_loc,max_loc = cv.minMaxLoc(result)
print(min_val,min_loc)
if md == cv.TM_SQDIFF_NORMED:# 根据不同的方法选择不同的参考值,# cv.TM_SQDIFF_NORMED最小时最相似,其他最大时最相似
tl = min_loc
else:
tl = max_loc
br = (tl[0] +tw,tl[1]+th)#选到点后,
cv.rectangle(target,tl,br,(0,0,255),2)#第2个点和第3个点参数分别代表矩形的左上角和右下角两个点
cv.namedWindow("match-",cv.WINDOW_AUTOSIZE)
cv.imshow("match",target)
cv.resizeWindow("match", 540, 960)
src = cv.imread("../images/lena.jpg")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow('input image', src)
template_demo()
cv.waitKey(0) # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
cv.destroyAllWindows()
理论
- 首先,模板匹配的方法如下:
这就是这些方法的数学原理,将模板图片的像素与待检测图片的各个像素做对应的数学操作,从而找出,我们要的点。
①TM_SQDIFF是平方差匹配;TM_SQDIFF_NORMED是标准平方差匹配。利用平方差来进行匹配,最好匹配为0.匹配越差,匹配值越大。
②TM_CCORR是相关性匹配;TM_CCORR_NORMED是标准相关性匹配。采用模板和图像间的乘法操作,数越大表示匹配程度较高, 0表示最坏的匹配效果。
③TM_CCOEFF是相关性系数匹配;TM_CCOEFF_NORMED是标准相关性系数匹配。将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列)。
总结:随着从简单的测量(平方差)到更复杂的测量(相关系数),我们可获得越来越准确的匹配(同时也意味着越来越大的计算代价)。
- 匹配的核心方法是:
result = cv.matchTemplate(target,tpl,md)
opencv的目标匹配函数为matchTemplate,函数原型为:matchTemplate(image, templ, method[, result[, mask]]) -> result
image参数表示待搜索源图像,必须是8位整数或32位浮点。
templ参数表示模板图像,必须不大于源图像并具有相同的数据类型。
method参数表示计算匹配程度的方法。
result参数表示匹配结果图像,必须是单通道32位浮点。如果image的尺寸为W x H,templ的尺寸为w x h,则result的尺寸为(W-w+1)x(H-h+1)。
其中result是模板图像去匹配的区域位置图像
这里值得注意的是:cv2.matchTemplate返回一个相关图,本质上是一个灰度图像,其中每个像素表示该像素的邻域与模板匹配多少。
- 第三个比较重要的方法是:
cv.minMaxLoc
我们关于这个的代码行是:min_val,max_val,min_loc,max_loc = cv.minMaxLoc(result)
MaxLoc表示matchTemplate返回的图像中强度最高的matchTemplate ,它与图像与模板的最佳匹配相对应(仅对于特定的相关方法,对于TM_SQDIFF或TM_SQDIFF_NORMED而言 ,最佳匹配是minVal )。
所以,哪个方法比较好的话,要根据你具体采用的方法得出的值去判断。 - 接下来就是将那个地方给圈起来了:
cv.rectangle(target,tl,br,(0,0,255),2)#第2个点和第3个点参数分别代表矩形的左上角和右下角两个点