引言
模板匹配是在一幅图像中寻找一个特定目标的方法之一。这种方法的原理非常简单,遍历图像中的每一个可能的位置,比较各处与模板是否“相似”,当相似度足够高时,就认为找到了我们的目标。
匹配方法
在 OpenCV 中,提供了相应的匹配函数完成这个操作:matchTemplate、 minMaxLoc
matchTemplate 函数:在模板和输入图像之间寻找匹配,获得匹配结果图像
minMaxLoc 函数:在给定的矩阵中寻找最大和最小值,并给出它们的位置
在具体介绍这两个函数之前呢,我们还要介绍一个概念,就是如何来评价两幅图像是否“相似”。
OpenCV 提供了 6 种计算两幅图像相似度的方法:
- 差值平方和匹配 CV_TM_SQDIFF
- 标准化差值平方和匹配 CV_TM_SQDIFF_NORMED
- 相关匹配 CV_TM_CCORR
- 标准相关匹配 CV_TM_CCORR_NORMED
- 相关匹配 CV_TM_CCOEFF
- 标准相关匹配 CV_TM_CCOEFF_NORMED
方法介绍
下面就分别来介绍。首先,先给出几个符号:
T(x,y) 用来表示我们的模板。I(x,y) 是我们的目标图像。 R(x,y) 是用来描述相似度的函数。
差值平方和匹配 CV_TM_SQDIFF
这类方法利用图像与模板各个像素差值的平方和来进行匹配,最好匹配为 0。 匹配越差,匹配值越大。
标准化差值平方和匹配 CV_TM_SQDIFF_NORMED
这个方法其实和差值平方和算法是类似的。只不过对图像和模板进行了标准化操作。
这种标准化操作可以保证当模板和图像各个像素的亮度都乘上了同一个系数时,相关度不发生变化。
也就是说当 I(x,y)和T(x,y) 变为k×I(x,y)和k×T(x,y) 时,R(x,y)不发生变化。
相关匹配 CV_TM_CCORR
这类方法采用模板和图像的互相关计算作为相似度的度量方法,所以较大的数表示匹配程度较高,0标识最坏的匹配效果。
标准化相关匹配 CV_TM_CCORR_NORMED
这个方法和 标准化差值平方和匹配 类似,都是去除了亮度线性变化对相似度计算的影响。可以保证图像和模板同时变亮或变暗k倍时结果不变。
相关匹配 CV_TM_CCOEFF
这种方法也叫做相关匹配,但是和上面的 CV_TM_CCORR 匹配方法还是有不通过的。简单的说,这里是把图像和模板都减去了各自的平均值,使得这两幅图像都没有直流分量。
标准相关匹配 CV_TM_CCOEFF_NORMED
这是 OpenCV 支持的最复杂的一种相似度算法。这里的相关运算就是数理统计学科的相关系数计算方法。具体的说,就是在减去了各自的平均值之外,还要各自除以各自的方差。经过减去平均值和除以方差这么两步操作之后,无论是我们的待检图像还是模板都被标准化了,这样可以保证图像和模板分别改变光照亮不影响计算结果。计算出的相关系数被限制在了 -1 到 1 之间,1 表示完全相同,-1 表示两幅图像的亮度正好相反,0 表示两幅图像之间没有线性关系。
实例演示:
代码如下
#导入cv模块
import cv2 as cv
import numpy as np
'''
匹配方法:
差值平方和匹配 CV_TM_SQDIFF
标准化差值平方和匹配 CV_TM_SQDIFF_NORMED
相关匹配 CV_TM_CCORR
标准相关匹配 CV_TM_CCORR_NORMED
相关匹配 CV_TM_CCOEFF
标准相关匹配 CV_TM_CCOEFF_NORMED
'''
def template_demo():
tpl=cv.imread("F:/Projects/images/tpl.png")
target=cv.imread("F:/Projects/images/target1.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
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)
print("------------Hi,Python!-------------")
# 读取图像,支持 bmp、jpg、png、tiff 等常用格式
src = cv.imread("F:/Projects/images/1.jpg")
#创建窗口并显示图像
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow("input image",src) #显示原图
template_demo()
cv.waitKey(0)
#释放窗口
cv.destroyAllWindows()
运行效果: