目标
在本教程中,您将学习如何:使用OpenCV功能matchTemplate()来搜索图像补丁和输入图像之间的匹配
使用OpenCV函数minMaxLoc()来查找给定数组中的最大值和最小值(以及它们的位置)。
理论
什么是模板匹配?
模板匹配是一种用于查找与模板图像(补丁)匹配(类似)的图像区域的技术。
虽然补丁必须是一个矩形,可能并不是所有的矩形都是相关的。在这种情况下,可以使用掩模来隔离应该用于找到匹配的补丁部分。
它是如何工作的?我们需要两个主要组件:源图像(I):我们期望找到与模板图像匹配的图像
模板图像(T):将与模板图像进行比较的补丁图像
我们的目标是检测最匹配的区域:
要识别匹配区域,我们必须通过滑动来比较模板图像与源图像:
通过滑动,我们的意思是一次移动补丁一个像素(从左到右,从上到下)。在每个位置,计算度量,以便它表示在该位置处的匹配的“好”还是“坏”(或者与图像的特定区域相似)。
对于T的每个位置超过I,则存储在该度量结果矩阵 R。R中的每个位置(x,y)都包含匹配度量
上面的图片是一个度量tm_ccorr_normed滑动补丁结果R。最亮的位置表示最高匹配。如您所见,红色圆圈标记的位置可能是具有最高值的位置,因此这个位置(由点形成的矩形,角度和宽度和高度等于补丁图像)被认为是匹配。实际上,我们使用函数minMaxLoc()定位R矩阵中最高的值(或更低的取决于匹配方法的类型)
mask是如何工作的?如果匹配需要屏蔽,则需要三个组件:源图像(I):我们期望找到与模板图像匹配的图像
模板图像(T):将与模板图像进行比较的补丁图像
掩模图像(M):The mask,屏蔽模板的灰度图像目前只有两种匹配方法接受掩码:CV_TM_SQDIFF和CV_TM_CCORR_NORMED(有关opencv中可用的所有匹配方法的说明,请参见下文)。
The mask必须与模板尺寸相同
The mask应具有CV_8U或CV_32F深度和与模板图像相同数量的通道。在CV_8U情况下,The mask值被视为二进制,即零和非零。在CV_32F情况下,值应该落在[0..1]范围内,并且模板像素将乘以相应的The mask像素值。由于样本中的输入图像具有CV_8UC3类型,因此屏蔽也被读取为彩色图像。
OpenCV中可以使用哪些匹配方法?
OpenCV在函数matchTemplate()中实现模板匹配。可用的方法有以上6种:method=CV_TM_SQDIFF
method=CV_TM_SQDIFF_NORMED
method=CV_TM_CCORR
method=CV_TM_CCORR_NORMED
method=CV_TM_CCOEFF
where
method=CV_TM_CCOEFF_NORMED
Code
C ++
这个程序是做什么的?加载输入图像,图像补丁(模板)和可选的mask
使用OpenCV函数matchTemplate()与之前描述的6种匹配方法中的任何一种执行模板匹配过程。用户可以通过在轨迹栏中输入其选择来选择该方法。如果提供了一个mask,它只会用于支持mask的方法
规范匹配过程的输出
以较高的匹配概率来定位位置
在与最高匹配相对应的区域周围绘制一个矩形可下载的代码:点击这里
代码一览:#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include
using namespace std;
using namespace cv;
bool use_mask;
Mat img; Mat templ; Mat mask; Mat result;
const char* image_window = "Source Image";
const char* result_window = "Result window";
int match_method;
int max_Trackbar = 5;
void MatchingMethod( int, void* );
int main( int argc, char** argv )
{
if (argc < 3)
{
cout << "Not enough parameters" << endl;
cout << "Usage:\n./MatchTemplate_Demo []" << endl;
return -1;
}
img = imread( argv[1], IMREAD_COLOR );
templ = imread( argv[2], IMREAD_COLOR );
if(argc > 3) {
use_mask = true;
mask = imread( argv[3], IMREAD_COLOR );
}
if(img.empty() || templ.empty() || (use_mask && mask.empty()))
{
cout << "Can't read one of the images" << endl;
return -1;
}
namedWindow( image_window, WINDOW_AUTOSIZE );
na