模板匹配是在一幅图像中寻找一个特定目标的方法之一。这种方法的原理非常简单,遍历图像中的每一个可能的位置,比较各处与模板是否“相似”,当相似度足够高时,就认为找到了我们的目标。
在 OpenCV 中,提供了相应的函数完成这个操作:
在具体介绍这两个函数之前呢,我们还要介绍一个概念,就是如何来评价两幅图像是否“相似”。
OpenCV 提供了 6 种计算两幅图像相似度的方法。
下面就分别来介绍。首先,先给出几个符号:
T(x,y)T(x,y) 用来表示我们的模板。I(x,y)I(x,y) 是我们的目标图像。 R(x,y)R(x,y) 是用来描述相似度的函数。
这类方法利用图像与模板各个像素差值的平方和来进行匹配,最好匹配为 0。 匹配越差,匹配值越大。
R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) − I ( x + x ′ , y + y ′ ) ) 2 R(x,y) = \sum_{x',y'}\left(T(x',y')-I(x+x',y+y')\right)^2 R(x,y)=x′,y′∑(T(x′,y′)−I(x+x′,y+y′))2
这个方法其实和差值平方和算法是类似的。只不过对图像和模板进行了标准化操作。
R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) − I ( x + x ′ , y + y ′ ) ) 2 ∑ x ′ , y ′ T ( x ′ , y ′ ) 2 ∑ x ′ , y ′ I ( x + x ′ , y + y ′ ) 2 R(x,y) = \frac{\sum_{x',y'}\left(T(x',y')-I(x+x',y+y')\right)^2}{\sqrt{\sum_{x',y'} T(x',y')^2 \sum_{x',y'}I(x+x',y+y')^2}} R(x,y)=∑x′,y′T(x′,y′)2∑x′,y′I(x+x′,y+y′)2∑x′,y′(T(x′,y′)−I(x+x′,y+y′))2
这种标准化操作可以保证当模板和图像各个像素的亮度都乘上了同一个系数时,相关度不发生变化。
也就是说当 I(x,y)I(x,y)和T(x,y)T(x,y) 变为k×I(x,y)k×I(x,y)和k×T(x,y)k×T(x,y) 时,R(x,y)R(x,y)不发生变化。
这类方法采用模板和图像的互相关计算作为相似度的度量方法,所以较大的数表示匹配程度较高,0标识最坏的匹配效果。
R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) × I ( x + x ′ , y + y ′ ) ) R(x,y) = \sum_{x',y'}\left(T(x',y')\times I(x+x',y+y')\right) R(x,y)=x′,y′∑(T(x′,y′)×I(x+x′,y+y′))
这个方法和 标准化差值平方和匹配 类似,都是去除了亮度线性变化对相似度计算的影响。可以保证图像和模板同时变亮或变暗k倍时结果不变。
R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) × I ( x + x ′ , y + y ′ ) ) ∑ x ′ , y ′ T ( x ′ , y ′ ) 2 ∑ x ′ , y ′ I ( x + x ′ , y + y ′ ) 2 R(x,y) = \frac{\sum_{x',y'}\left(T(x',y')\times I(x+x',y+y')\right)}{\sqrt{\sum_{x',y'} T(x',y')^2 \sum_{x',y'}I(x+x',y+y')^2}} R(x,y)=∑x′,y′T(x′,y′)2∑x′,y′I(x+x′,y+y′)2∑x′,y′(T(x′,y′)×I(x+x′,y+y′))
这种方法也叫做相关匹配,但是和上面的 CV_TM_CCORR 匹配方法还是有不通过的。简单的说,这里是把图像和模板都减去了各自的平均值,使得这两幅图像都没有直流分量。
T ′ ( x , y ) = T ( x , y ) − ∑ x ′ , y ′ T ( x ′ , y ′ ) w × h I ′ ( x , y ) = I ( x , y ) − ∑ x ′ , y ′ I ( x ′ , y ′ ) w × h R ( x , y ) = ∑ x ′ , y ′ ( T ′ ( x ′ , y ′ ) × I ′ ( x + x ′ , y + y ′ ) ) T'(x,y) = T(x,y) - \frac{\sum_{x',y'} T(x',y')}{w\times h} \\ I'(x,y) = I(x,y) - \frac{\sum_{x',y'} I(x',y')}{w\times h} \\ R(x,y) = \sum_{x',y'}\left(T'(x',y')\times I'(x+x',y+y')\right) T′(x,y)=T(x,y)−w×h∑x′,y′T(x′,y′)I′(x,y)=I(x,y)−w×h∑x′,y′I(x′,y′)R(x,y)=x′,y′∑(T′(x′,y′)×I′(x+x′,y+y′))
这是 OpenCV 支持的最复杂的一种相似度算法。这里的相关运算就是数理统计学科的相关系数计算方法。具体的说,就是在减去了各自的平均值之外,还要各自除以各自的方差。经过减去平均值和除以方差这么两步操作之后,无论是我们的待检图像还是模板都被标准化了,这样可以保证图像和模板分别改变光照亮不影响计算结果。计算出的相关系数被限制在了 -1 到 1 之间,1 表示完全相同,-1 表示两幅图像的亮度正好相反,0 表示两幅图像之间没有线性关系。
T ′ ( x , y ) = T ( x , y ) − 1 w × h ∑ x ′ , y ′ T ( x ′ , y ′ ) ∑ x ′ , y ′ T ( x ′ , y ′ ) 2 I ′ ( x , y ) = I ( x , y ) − 1 w × h ∑ x ′ , y ′ I ( x ′ , y ′ ) ∑ x ′ , y ′ I ( x ′ , y ′ ) 2 R ( x , y ) = ∑ x ′ , y ′ ( T ′ ( x ′ , y ′ ) × I ′ ( x + x ′ , y + y ′ ) ) T'(x,y) = \frac{T(x,y) - \frac{1}{w\times h} \sum_{x',y'} T(x',y')}{ \sqrt{\sum_{x',y'} T(x',y')^2}} \\ I'(x,y) =\frac{ I(x,y) - \frac{1}{w\times h}\sum_{x',y'} I(x',y')}{ \sqrt{\sum_{x',y'} I(x',y')^2}} \\ R(x,y) = \sum_{x',y'}\left(T'(x',y')\times I'(x+x',y+y')\right) T′(x,y)=∑x′,y′T(x′,y′)2T(x,y)−w×h1∑x′,y′T(x′,y′)I′(x,y)=∑x′,y′I(x′,y′)2I(x,y)−w×h1∑x′,y′I(x′,y′)R(x,y)=x′,y′∑(T′(x′,y′)×I′(x+x′,y+y′))