本文使用python实现。
OpenCV中模板匹配使用的公式如下
函数(1):平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
函数(2):归一化平方差匹配法
函数(3):相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
函数(4):归一化相关匹配法
函数(5):相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
函数(6):归一化相关系数匹配法
代码如下
import cv2 as cv
import numpy as np
def template_demo():
tpl = cv.imread("C:/Users/admin/Desktop/sample.jpg")
target = cv.imread("C:/Users/admin/Desktop/bird.jpg")
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)
'''
def matchTemplate(image: Any, # 待匹配的源图像
templ: Any, # 模板图像
method: Any, # 模板匹配算法
result: Any = None, # 保存结果,我们可以通过minMaxLoc()确定结果矩阵的最大值和最小值的位置.
mask: Any = None) -> None
关于模板匹配算法,有以下6种:
enum {
TM_SQDIFF=0, # 平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
TM_SQDIFF_NORMED=1, # 归一化平方差匹配法
TM_CCORR=2, # 相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
TM_CCORR_NORMED=3, # 归一化相关匹配法
TM_CCOEFF=4, # 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
TM_CCOEFF_NORMED=5 }; # 归一化相关系数匹配法
TM_SQDIFF,TM_SQDIFF_NORMED匹配数值越低表示匹配效果越好,其它四种反之。
TM_SQDIFF_NORMED,TM_CCORR_NORMED,TM_CCOEFF_NORMED是标准化的匹配,得到的最大值,最小值范围在0~1之间,其它则需要自己对结果矩阵归一化。
不同的方法会得到差异很大的结果,可以通过测试选择最合适的方法。
'''
min_val, max_val, min_loc, max_loc = cv.minMaxLoc(result)
'''
def minMaxLoc(src: Any,
mask: Any = None) -> None
函数功能:假设有一个矩阵a,现在需要求这个矩阵的最小值,最大值,并得到最大值,最小值的索引。
使用这个cv2.minMaxLoc()函数就可全部解决。函数返回的四个值就是上述所要得到的。
'''
if md == 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) # 在图上绘制矩形
'''
def rectangle(img: Any, # 图像
pt1: Any, # 矩形的一个顶点
pt2: Any, # 矩形对角线上的另一个顶点
color: Any, # 矩形线条颜色(RGB)或亮度(灰度图像),(0, 0, 255)表示红色
thickness: Any = None, # 组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。
lineType: Any = None, # 线条的类型
shift: Any = None) -> None # 坐标点的小数点位数。
'''
cv.imshow("match-"+np.str(md), target)
template_demo()
cv.waitKey(0)
cv.destroyAllWindows()
使用cv.TM_SQDIFF_NORMED计算出的结果:
使用cv.TM_CCORR_NORMED计算出的结果
使用cv.TM_CCOEFF_NORMED计算出的结果
这三种方式都可以得到正确结果。