【OpenCV 4开发详解】图像模板匹配

本文首发于 “小白学视觉”微信公众号,欢迎关注公众号
本文作者为小白,版权归 人民邮电出版社发行所有,禁止转载,侵权必究!

经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。

前面我们通过图像直方图反向投影的方式在图像中寻找模板图像,由于直方图不能直接反应图像的纹理,因此如果两张不同模板图像具有相同的直方图分布特性,那么在同一张图中对这两张模板图像的直方图进行反向投影,最终结果将不具有参考意义。因此,我们在图像中寻找模板图像时,可以直接通过比较图像像素的形式来搜索是否存在相同的内容,这种通过比较像素灰度值来寻找相同内容的方法叫做图像的模板匹配。

模板匹配常用于在一幅图像中寻找特定内容的任务中。由于模板图像的尺寸小于待匹配图像的尺寸,同时又需要比较两张图像中的每一个像素的灰度值,因此常采用在待匹配图像中选择与模板相同尺寸的滑动窗口,通过比较滑动窗口与模板的相似程度,判断待匹配图像中是否含有与模板图像相同的内容,其原理如图4-11所示。

【OpenCV 4开发详解】图像模板匹配_第1张图片
图4-11 模板匹配示意图

在图4-11中,右侧4×4的图像是模板图像,每个像素中的数字是该像素的灰度值,左侧8×8图像是待匹配图像,模板匹配的流程如下:

  • Step1:在待匹配图像中选取与模板尺寸大小相同的滑动窗口,如图4-11中的阴影区域所示。
  • Step2:比较滑动窗口中每个像素与模板中对应像素灰度值的关系,计算模板与滑动窗口的相似性。
  • Step3:将滑动窗口从左上角开始先向右滑动,滑动到最右边后向下滑动一行,从最左侧重新开始滑动,记录每一次移动后计算的模板与滑动窗口的相似性。
  • Step4:比较所有位置的相似性,选择相似性最大的滑动窗口作为备选匹配结果。

OpenCV 4中提供了用于图像模板匹配的函数matchTemplate(),该函数能够实现模板匹配过程中图像与模板相似性的计算,在代码清单4-12中给出了函数原型。

代码清单4-12 matchTemplate()函数原型
1.	void cv::matchTemplate(InputArray  image,
2.	                            InputArray  templ,
3.	                            OutputArray  result,
4.	                            int  method,
5.	                            InputArray  mask = noArray() 
6.	                            )
  • image:待模板匹配的原图像,图像数据类型为CV_8U和CV_32F两者中的一个。
  • templ:模板图像,需要与image具有相同的数据类型,但是尺寸不能大于image。
  • result:模板匹配结果输出图像,图像数据类型为CV_32F。如果image的尺寸为W×H,模板图像尺寸为w×h,则输出图像的尺寸为(W-w+1)×(H-h+1)。
  • method:模板匹配方法标志,可选择参数及含义在表4-3中给出。
  • mask:匹配模板的掩码,必须与模板图像具有相同的数据类型和尺寸,默认情况下不设置,目前仅支持在TM_SQDIFF和TM_CCORR_NORMED这两种匹配方法时使用。

该函数同时支持灰度图像和彩色图像两种图像的模板匹配。函数前两个参数为输入的原图像和模板图像,由于是在原图像中搜索是否存在与模板图像相同的内容,因此需要模板图像的尺寸小于原图像,并且两者必须具有相同的数据类型。第三个参数为相似性矩阵,滑动窗口与模板的相似性系数存放在滑动窗口左上角第一个像素处,因此输出的相似性矩阵尺寸要小于原图像的尺寸,如果image的尺寸为W×H,模板图像尺寸为w×h,则输出图像的尺寸为(W-w+1)×(H-h+1)。因为在模板匹配中原图像不需要进行尺寸的外延,所以滑动窗口左上角可以移动的范围要小于原图像的尺寸。无论输入的是彩色图像还是灰度图像,函数输出结果都是单通道矩阵。了解相似性系数记录的方式便于寻找到与模板最相似的滑动窗口,继而在原图中标记出与模板相同的位置。函数第四个参数是滑动窗口与模板相似性系数的计算方式,OpenCV 4提供了多种计算方法,所有可以选择的标志参数在表4-3中给出,接下来对每一种方法进行详细介绍。

表4-3 matchTemplate()函数模板匹配方法选择标志参数
标志参数 简记 作用
TM_SQDIFF 0 平方差匹配法
TM_SQDIFF_NORMED 1 归一化平方差匹配法
TM_CCORR 2 相关匹配法
TM_CCORR_NORMED 3 归一化相关匹配法
TM_CCOEFF 4 系数匹配法
TM_CCOEFF_NORMED 5 归一化相关系数匹配法
(1)TM_SQDIFF:

该方法名为平方差匹配法,计算的公式如式(6.9)所示,这种方法利用平方差来进行匹配,当模板与滑动窗口完全匹配时计算数值为0,两者匹配度越低计算数值越大。
R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) − I ( x + x ′ , y + y ′ ) ) 2 (6.9) R(x,y) = \sum\limits_{x',y'} {{{(T(x',y') - I(x + x',y + y'))}^2}} \tag{6.9} R(x,y)=x,y(T(x,y)I(x+x,y+y))2(6.9)
其中 表示模板图像, 表示原图像。

(2)TM_SQDIFF_NORMED:

该方法名为归一化平方差匹配方法,计算公式如式(6.10)所示,这种方法是将平方差方法进行归一化,使得输入结果缩放到了0到1之间,当模板与滑动窗口完全匹配时计算数值为0,两者匹配度越低计算数值越大。
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 (6.10) R(x,y) = \frac{{\sum\limits_{x',y'} {{{(T(x',y') - I(x + x',y + y'))}^2}} }}{{\sqrt {\sum\limits_{x',y'} {T{{(x',y')}^2}} * \sum\limits_{x',y'} {I{{(x + x',y + y')}^2}} } }} \tag{6.10} R(x,y)=x,yT(x,y)2x,yI(x+x,y+y)2 x,y(T(x,y)I(x+x,y+y))2(6.10)

(3)TM_CCORR:

该方法名为相关匹配法,计算公式如式(6.11)所示,这类方法采用模板和图像间的乘法操作,所以数值越大表示匹配效果越好,0表示最坏的匹配结果。
R ( x , y ) = ∑ x ′ , y ′ ( T ( x ′ , y ′ ) ∗ I ( x + x ′ , y + y ′ ) ) (6.11) R(x,y) = \sum\limits_{x',y'} {(T(x',y') * I(x + x',y + y'))} \tag{6.11} R(x,y)=x,y(T(x,y)I(x+x,y+y))(6.11)

(4)TM_CCORR_NORMED:

该方法名为归一化相关匹配法,计算公式如式(6.12)所示,这种方法是将相关匹配法进行归一化,使得输入结果缩放到了0到1之间,当模板与滑动窗口完全匹配时计算数值为1,两者完全不匹配时计算结果为0。
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 (6.12) R(x,y) = \frac{{\sum\limits_{x',y'} {{{(T(x',y') * I(x + x',y + y'))}^2}} }}{{\sqrt {\sum\limits_{x',y'} {T{{(x',y')}^2}} * \sum\limits_{x',y'} {I{{(x + x',y + y')}^2}} } }} \tag{6.12} R(x,y)=x,yT(x,y)2x,yI(x+x,y+y)2 x,y(T(x,y)I(x+x,y+y))2(6.12)

(5)TM_CCOEFF:

该方法名为系数匹配法,计算公式如式(6.13)所示,这种方法采用相关匹配方法对模板减去均值的结果和原图像减去均值的结果进行匹配,这种方法可以很好的解决模板图像和原图像之间由于亮度不同而产生的影响。该方法中模板与滑动窗口匹配度越高计算数值越大,匹配度越低计算数值越小,并且该方法计算结果可以为负数。
R ( x , y ) = ∑ x ′ , y ′ ( T ′ ( x ′ , y ′ ) ∗ I ′ ( x + x ′ , y + y ′ ) ) (6.13) R(x,y) = \sum\limits_{x',y'} {(T'(x',y') * I'(x + x',y + y'))} \tag{6.13} R(x,y)=x,y(T(x,y)I(x+x,y+y))(6.13)
其中:
{ T ′ ( x ′ , y ′ ) = T ( x ′ , y ′ ) − 1 w ∗ h ∑ x ′ ′ , y ′ ′ T ( x ′ ′ , y ′ ′ ) I ′ ( x + x ′ , y + y ′ ) = I ( x + x ′ , y + y ′ ) − 1 w ∗ h ∑ x ′ ′ , y ′ ′ I ( x + x ′ ′ , y + y ′ ′ ) (6.14) \left\{ {\begin{matrix} {T'(x',y') = T(x',y') - \frac{1}{{w * h}}\sum\limits_{x'',y''} {T(x'',y'')} }\\ {I'(x + x',y + y') = I(x + x',y + y') - \frac{1}{{w * h}}\sum\limits_{x'',y''} {I(x + x'',y + y'')} } \end{matrix}} \right. \tag{6.14} T(x,y)=T(x,y)wh1x,yT(x,y)I(x+x,y+y)=I(x+x,y+y)wh1x,yI(x+x,y+y)(6.14)

(6)TM_CCOEFF_NORMED:

该方法名为归一化系数匹配法,计算公式如式(6.15)所示,这种方法将系数匹配方法进行归一化,使得输入结果缩放到了1到-1之间,当模板与滑动窗口完全匹配时计算数值为1,当两者完全不匹配时计算结果为-1。
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 (6.15) R(x,y) = \frac{{\sum\limits_{x',y'} {(T'(x',y') * I'(x + x',y + y'))} }}{{\sqrt {\sum\limits_{x',y'} {T{{(x',y')}^2} * \sum\limits_{x',y'} {I'{{(x + x',y + y')}^2}} } } }} \tag{6.15} R(x,y)=x,yT(x,y)2x,yI(x+x,y+y)2 x,y(T(x,y)I(x+x,y+y))(6.15)

了解不同的计算相似性方法时,重点需要知道在每种方法中最佳匹配结果的数值应该是较大值还是较小值,由于matchTemplate()函数的输出结果是存有相关性系数的矩阵,因此需要通过minMaxLoc()函数去寻找输入矩阵中的最大值或者最小值,进而确定模板匹配的结果。

通过寻找输出矩阵的最大值或者最小值得到的只是一个像素点,需要以该像素点为矩形区域的左上角,绘制与模板图像同尺寸的矩形框,标记出最终匹配的结果。为了了解图像模板匹配相关函数的使用方法,在代码清单4-13中给出了在彩色图像中进行模板匹配的示例程序。程序中采用TM_CCOEFF_NORMED方法计算相关性系数,通过minMaxLoc()函数寻找相关性系数中的最大值,确定最佳匹配值的像素点坐标,之后在原图中绘制出与模板最佳匹配区域的范围,程序的运行结果在图4-12中给出。

代码清单4-13 myMatchTemplate.cpp图像的模板匹配
1.	#include <opencv2\opencv.hpp>
2.	#include <iostream>
3.	
4.	using namespace cv;
5.	using namespace std;
6.	
7.	int main()
8.	{
9.		Mat img = imread("lena.png");
10.		Mat temp = imread("lena_face.png");
11.		if (img.empty() || temp.empty())
12.		{
13.			cout << "请确认图像文件名称是否正确" << endl;
14.			return -1;
15.		}
16.		Mat result;
17.		matchTemplate(img, temp, result, TM_CCOEFF_NORMED);//模板匹配
18.		double maxVal, minVal;
19.		Point minLoc, maxLoc;
20.		//寻找匹配结果中的最大值和最小值以及坐标位置
21.		minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
22.		//绘制最佳匹配区域
23.		rectangle(img,cv::Rect(maxLoc.x,maxLoc.y,temp.cols,temp.rows),Scalar(0,0,255),2);
24.		imshow("原图", img);
25.		imshow("模板图像", temp);
26.		imshow("result", result);
27.		waitKey(0);
28.		return 0;
29.	}
【OpenCV 4开发详解】图像模板匹配_第2张图片
图4-12 myMatchTemplate.cpp程序运行结果

 

OpenCV 4开发详解
往期推荐
【OpenCV 4开发详解】安装过程中问题解决方案
【OpenCV 4开发详解】了解OpenCV的模块架构
【OpenCV 4开发详解】Mat类介绍
【OpenCV 4开发详解】Mat类构造与赋值
【OpenCV 4开发详解】4种读取Mat类元素的的方法
【OpenCV 4开发详解】图像的读取与显示
【OpenCV 4开发详解】视频加载与摄像头调用
【OpenCV 4开发详解】图像与视频的保存
【OpenCV 4开发详解】保存和读取XML和YMAL文件
【OpenCV 4开发详解】颜色模型与转换
【OpenCV 4开发详解】多通道分离与合并
【OpenCV 4开发详解】图像像素统计
【OpenCV 4开发详解】两图像间的像素操作
【OpenCV 4开发详解】图像二值化
【OpenCV 4开发详解】图像LUT查找表
【OpenCV 4开发详解】图像连接
【OpenCV 4开发详解】图像仿射变换
【OpenCV 4开发详解】图像透视变换
【OpenCV 4开发详解】图像极坐标变换
【OpenCV 4开发详解】图像上绘制几何图形
【OpenCV 4开发详解】图像金字塔
【OpenCV 4开发详解】窗口交互操作
【OpenCV 4开发详解】图像直方图绘制
【OpenCV 4开发详解】直方图操作
【OpenCV 4开发详解】直方图应用
经过几个月的努力,市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》将春节后由人民邮电出版社发行。如果小伙伴觉得内容有帮助,希望到时候多多支持!
关注小白的小伙伴可以提前看到书中的内容,我们创建了学习交流群,欢迎各位小伙伴添加小白微信加入交流群,添加小白时请备注“学习OpenCV 4”。

你可能感兴趣的:(OpenCV,4开发详解)