opencv 模板匹配(cvMatchTemplate)
模板匹配是通过在输入图像上滑动模板图像块对实际的图像块和输入图像进行匹配,并且可以利用函数cvMinMaxLoc()找到最佳匹配的位置。例如在工业应用中,可以锁定图像中零部件的位置,并根据具体的位置,进行具体的处理。匹配的过程中可以使用不同的method,通过最合适的method,进行最合适的匹配。
MatchTemplate
比较模板和重叠的图像区域
void cvMatchTemplate( const CvArr* image,const CvArr* templ, CvArr* result, int method );
- image 欲搜索的图像。它应该是单通道、8-比特或32-比特 浮点数图像templ 搜索模板,不能大于输入图像,且与输入图像具有一样的数据类型result 比较结果的映射图像。单通道、32-比特浮点数. 如果图像是 W×H 而 templ 是 w×h ,则 result 一定是 (W-w+1)×(H-h+1).method 指定匹配方法:
函数 cvMatchTemplate 与函数 cvCalcBackProjectPatch 类似。它滑动过整个图像 image, 用指定方法比较 templ 与图像尺寸为 w×h 的重叠区域,并且将比较结果存到 result 中。 下面是不同的比较方法,可以使用其中的一种 (I 表示图像,T - 模板, R - 结果. 模板与图像重叠区域 x'=0..w-1, y'=0..h-1 之间求和):
OpenCV模板匹配算法.可用的方法有6个:
平方差匹配method=CV_TM_SQDIFF,这类方法利用平方差来进行匹配,最好匹配为0.匹配越差,匹配值越大.
标准平方差匹配method=CV_TM_SQDIFF_NORMED
相关匹配method=CV_TM_CCORR,这类方法采用模板和图像间的乘法操作,所以较大的数表示匹配程度较高,0标识最坏的匹配效果.
标准相关匹配method=CV_TM_CCORR_NORMED
相关系数匹配method=CV_TM_CCOEFF。这类方法将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列).
在这里
标准相关系数匹配method=CV_TM_CCOEFF_NORMED
通常,随着从简单的测量(平方差)到更复杂的测量(相关系数),我们可获得越来越准确的匹配(同时也意味着越来越大的计算代价).最好的办法是对所有这些设置多做一些测试实验,以便为自己的应用选择同时兼顾速度和精度的最佳方案.
通过使用 cvMinMaxLoc函数,我们确定结果矩阵 R 的最大值和最小值的位置。函数中的参数有:
double minVal; double maxVal; Point minLoc; Point maxLoc;
Point matchLoc;
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
result: 匹配结果矩阵
&minVal 和 &maxVal: 在矩阵 result 中存储的最小值和最大值。该值是矩阵中的最大值和最小值。
&minLoc 和 &maxLoc: 在结果矩阵中最小值和最大值的坐标.
Mat(): 可选的掩模
代码如下(输出待寻找模板的位置坐标,以及相似度值):
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <string>using namespace cv;
using namespace std;#include "cv.h"
#include "highgui.h"#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <float.h>
#include <limits.h>
#include <time.h>
#include <ctype.h>int main(int argc, char** argv){IplImage *src, *temp1, *ftmp;//读入模板图像 temp1 = cvLoadImage(argv[1], 1);//读入源图像 src = cvLoadImage(argv[2], 1);int iwidth = src->width - temp1->width + 1;int iheight = src->height - temp1->height + 1;ftmp = cvCreateImage(cvSize(iwidth, iheight), 32, 1);double min_val;double max_val;CvPoint min_loc;CvPoint max_loc;cvMatchTemplate(src, temp1, ftmp, CV_TM_SQDIFF);cvMinMaxLoc(ftmp, &min_val, &max_val, &min_loc, &max_loc, NULL);cvRectangle(src, cvPoint(min_loc.x, min_loc.y), cvPoint((min_loc.x + temp1->width), (min_loc.y + temp1->height)), CV_RGB(0, 255, 0), 1);cvNamedWindow("src", 1);cvShowImage("src", src);printf("x_location=%d;y_location=%d", min_loc.x, min_loc.y);printf("min_val=%d;max_val=%d", min_val, max_val);cvWaitKey(0);return 0;
}
待搜寻的图: