在直方图介绍完,后面有个小小的内容,那就是模板匹配,这里的模板匹配可不是依据直方图进行的,而是通过输入图像上滑动图像块对实际的图像块和输入图像进行匹配。如下图所示:
在OpenCV中给出了模板匹配的函数cvMatchTemplate(),下面简要介绍下这个函数:
void cvMatchTemplate(
const CvArr* image,//输入图像,8位或浮点型单通道或者是彩色图像
const CvArr* templ,//模板图像
CvArr* result,//输出目标图像,单通道8位或者是浮点图像
int method//采用的匹配方法
)
//result的大小为image->width-templ->width+1,image->height-templ->height+1;
关于参数method,有很多种匹配方式:
**CV_TM_SQDIFF 平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
CV_TM_CCORR 相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
CV_TM_SQDIFF_NORMED 归一化平方差匹配法
CV_TM_CCORR_NORMED 归一化相关匹配法
CV_TM_CCOEFF_NORMED 归一化相关系数匹配法
那么**还有一个问题,我们怎样在result中获得最佳匹配区域呢?
**使用函数cvMinMaxLoc(result,&min_val,&max_val,&min_loc,&max_loc,NULL);从result中提取最大值(相似度最高)以及最大值的位置(即在result中该最大值max_val的坐标位置max_loc,即模板滑行时左上角的坐标,类似于图中的坐标(x,y))
由此得到:rect=cvRect(max_loc.x,max_loc.y,max_loc.x+templ->width,max_loc.y+templ->height);rect表示的矩形区域即是最佳的匹配区域。**
下面给出这个程序的完整示例:
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
int main()
{
int image_width, image_height, templ_width, templ_height, res_width, res_height;
double min_val, max_val;
CvPoint min_loc, max_loc;
//输入图像和模板图像
IplImage *image = cvLoadImage("1.jpg", CV_LOAD_IMAGE_UNCHANGED);
IplImage *templ = cvLoadImage("2.jpg", CV_LOAD_IMAGE_UNCHANGED);
image_width = image->width;
image_height = image->height;
templ_width = templ->width;
templ_height = templ->height;
res_width = image_width - templ_width+1;
res_height = image_height - templ_height + 1;
//输出目标图像,单通道的8位或者是32位浮点图像
IplImage *res = cvCreateImage(cvSize(res_width,res_height), IPL_DEPTH_32F, 1);
//调用模板匹配函数,采用的是CV_TM_SQDIFF平方差匹配法
cvMatchTemplate(image, templ, res, CV_TM_SQDIFF);
//用红色框出匹配的图像
cvMinMaxLoc(res, &min_val, &max_val, &min_loc, &max_loc,0);
//cvRectangle()函数中cvPoint(),cvPoint()分别为矩形框的两个对角点
cvRectangle(image,
cvPoint(min_loc.x, min_loc.y),
cvPoint(min_loc.x + templ_width, min_loc.y + templ_height),
cvScalar(0, 0, 255, 0), 1, 0, 0);
cvShowImage("Tep", templ);
cvShowImage("Src", image);
cvWaitKey();
cvReleaseImage(&image);
cvReleaseImage(&templ);
cvReleaseImage(&res);
cvDestroyAllWindows();
return 0;
}
运行结果如下:
大家如果感兴趣,可以修改下匹配方式看看匹配效果。