1.模板匹配原理
模板匹配是一种最原始、最基本的模式识别方法,研究某一特定对象物的图案位于图像的什么地方,进而识别对象物,这就是一个匹配问题。它是图像处理中最基本、最常用的匹配方法。模板匹配具有自身的局限性,主要表现在它只能进行平行移动,若原图像中的匹配目标发生旋转或大小变化,该算法无效。
模板匹配就是在整个图像区域发现与给定子图像匹配的小块区域,所以模板匹配首先需要一个模板图像T,还需要一个待检测的源图像S。
其方法为在待检测图像中,从左到右,从上至下,计算模板图像与重叠子图像的匹配度,匹配度越高,两者相同的可能性越高。
2.模板匹配算法
1.平方差匹配(CV_TM_SQDIFF)
值越大,匹配程度越差
2.标准平方差匹配(CV_TM_SQDIFF_NORMED)
3.相关匹配(CV_TM_CCORR)
这类方法采用模板和图像间的乘法操作,所以较大的数表示匹配程度较高,0标识最坏的匹配效果.
4.标准相关匹配(CV_TM_CCORR_NORMED)
5.相关匹配(CV_TM_CCOEFF)
这类方法将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列).
6.标准相关匹配(CV_TM_CCOEFF_NORMED)
3.步骤
首先我们要读取模板图像和目标图像,接下来我们可以用一个数组来表示模板匹配的方法,以供选择,然后我们要得到模板图像的宽和高,利用for循环来尝试匹配方法,此时我们会用到matchTemplate这个API,其参数为:
目标图像,模板图像,匹配结果图像,匹配方法
之后我们要在匹配结果图像中找到匹配结果中的最大值、最小值及其所在位置,最后我们就用矩形方框在图像中标注出来。
其代码为:
def template_demo():
tpl = cv.imread("D:/opencv3/image/lenaT1.png")
target = cv.imread("D:/opencv3/image/lena.png")
cv.imshow("template image", tpl)
cv.imshow("target image", 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) # 找到最大值和最小值
if md == cv.TM_SQDIFF_NORMED:
tl = min_Loc # tl是左上角点
else:
tl = max_Loc
br = (tl[0] + tw, tl[1] + th) # 右下角点
cv.rectangle(target, tl, br, (0, 0, 255), 2)
cv.imshow("match-"+np.str(md), target)
模板图像为:
目标图像为:
其匹配结果依次为:
这就是模板匹配后的结果。
完整代码
import cv2 as cv # 导入opencv模块
import numpy as np # 导入数学函数库
def template_demo():
tpl = cv.imread("D:/opencv3/image/lenaT1.png")
target = cv.imread("D:/opencv3/image/lena.png")
cv.imshow("template image", tpl)
cv.imshow("target image", 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) # 获得像素特征值集合
# 目标图像,模板图像,方法
"""
CV_TM_SQDIFF 差值平方和匹配, CV_TM_SQDIFF_NORMED 标准化差值平方和匹配,
CV_TM_CCORR 相关匹配, CV_TM_CCORR_NORMED 标准相关匹配,
CV_TM_CCOEFF 相关匹配, CV_TM_CCOEFF_NORMED 标准相关匹配
"""
min_Val, max_Val, min_Loc, max_Loc = cv.minMaxLoc(result) # 找到最大值和最小值
if md == cv.TM_SQDIFF_NORMED:
tl = min_Loc # tl是左上角点
else:
tl = max_Loc
br = (tl[0] + tw, tl[1] + th) # 右下角点
cv.rectangle(target, tl, br, (0, 0, 255), 2)
cv.imshow("match-"+np.str(md), target)
# cv.imshow("match-" + np.str(md), result)
print("------------hello python!------------")
template_demo()
cv.waitKey(0)
cv.destroyAllWindows() # 释放所有窗口