模板匹配——在一幅图像中匹配与模板相似的单个或者多个目标
(1)目标匹配函数:
cvMatchTemplate( const CvArr* image, constCvArr* templ,
CvArr* result,int method );
Image 待搜索图像
Templ 模板图像
Result 匹配结果 用来存放通过以下方法计算出滑动窗口与模板的相似值
Method 计算匹配程度的方法
关于匹配方法,使用不同的方法产生的结果的意义可能不太一样,有些返回的值越大表示匹配程度越好,而有些方法返回的值越小表示匹配程度越好
关于参数 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归一化相关系数匹配法
(2):接着就是要找最值以及最值对应的坐标
cvMinMaxLoc()寻找一个矩阵中最大最小值以及相应的坐标
cvMinMaxLoc( constCvArr* arr, double* min_val, double* max_val,
CvPoint* min_locCV_DEFAULT(NULL),
CvPoint* max_locCV_DEFAULT(NULL),
const CvArr* mask CV_DEFAULT(NULL) );
单目标匹配结果:
代码:
#include <iostream> #include "cv.h" #include "cxcore.h" #include "highgui.h" using namespace std; int main() { IplImage *src = cvLoadImage("E:\\study_opencv_video\\lesson16_1\\images\\src.jpg", 0); IplImage *srcResult = cvLoadImage("E:\\study_opencv_video\\lesson16_1\\images\\src.jpg", 3); //用来显示 IplImage *templat = cvLoadImage("E:\\study_opencv_video\\lesson16_1\\images\\template.png", 0); IplImage *result; if(!src || !templat) { cout << "打开图像失败"<< endl; return 0; } int srcW, srcH, templatW, templatH, resultH, resultW; srcW = src->width; srcH = src->height; templatW = templat->width; templatH = templat->height; if(srcW < templatW || srcH < templatH) { cout <<"模板不能比原图像小" << endl; return 0; } resultW = srcW - templatW + 1; resultH = srcH - templatH + 1; result = cvCreateImage(cvSize(resultW, resultH), 32, 1); cvMatchTemplate(src, templat, result, CV_TM_SQDIFF); double minValue, maxValue; CvPoint minLoc, maxLoc; cvMinMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc); cvRectangle(srcResult, minLoc, cvPoint(minLoc.x + templatW, minLoc.y+ templatH), cvScalar(0,0,255)); cvNamedWindow("srcResult", 0); cvNamedWindow("templat", 0); cvShowImage("srcResult", srcResult); cvShowImage("templat", templat); cvWaitKey(0); cvReleaseImage(&result); cvReleaseImage(&templat); cvReleaseImage(&srcResult); cvReleaseImage(&src); return 0; }
(3)多目标匹配:
结果:
代码:
#include <iostream> #include "cv.h" #include "cxcore.h" #include "highgui.h" using namespace std; CvPoint getNextMinLoc(IplImage *result, CvPoint minLoc, int maxVaule, int templatW, int templatH) { // 先将第一个最小值点附近两倍模板宽度和高度的都设置为最大值防止产生干扰 int startX = minLoc.x - templatW; int startY = minLoc.y - templatH; int endX = minLoc.x + templatW; int endY = minLoc.y + templatH; if(startX < 0 || startY < 0) { startX = 0; startY = 0; } if(endX > result->width - 1 || endY > result->height - 1) { endX = result->width - 1; endY = result->height - 1; } int y, x; for(y = startY; y < endY; y++) { for(x = startX; x < endX; x++) { cvSetReal2D(result, y, x, maxVaule); } } // 然后得到下一个最小值并且返回 double new_minVaule, new_maxValue; CvPoint new_minLoc, new_maxLoc; cvMinMaxLoc(result, &new_minVaule, &new_maxValue, &new_minLoc, &new_maxLoc); return new_minLoc; } int main() { IplImage *src = cvLoadImage("E:\\study_opencv_video\\lesson16_1\\images\\src.jpg", 0); IplImage *srcResult = cvLoadImage("E:\\study_opencv_video\\lesson16_1\\images\\src.jpg", 3); //用来显示 IplImage *templat = cvLoadImage("E:\\study_opencv_video\\lesson16_1\\images\\template.png", 0); IplImage *result; // 用来存放结果 if(!src || !templat) { cout << "打开图片失败" << endl; return 0; } int srcW, srcH, templatW, templatH, resultH, resultW; srcW = src->width; srcH = src->height; templatW = templat->width; templatH = templat->height; if(srcW < templatW || srcH < templatH) { cout << "模板不能比原图小" << endl; return 0; } resultW = srcW - templatW + 1; resultH = srcH - templatH + 1; result = cvCreateImage(cvSize(resultW, resultH), 32, 1); // 匹配方法计算的结果最小值为float cvMatchTemplate(src, templat, result, CV_TM_SQDIFF); double minValue, maxValue; CvPoint minLoc, maxLoc; cvMinMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc); cvRectangle(srcResult, minLoc, cvPoint(minLoc.x + templatW, minLoc.y+ templatH), cvScalar(0,0,255)); CvPoint new_minLoc; // 计算下一个最小值 new_minLoc = getNextMinLoc(result, minLoc, maxValue, templatW, templatH); cvRectangle(srcResult, new_minLoc, cvPoint(new_minLoc.x + templatW, new_minLoc.y+ templatH), cvScalar(0,0,255)); // 再下一个 new_minLoc = getNextMinLoc(result, new_minLoc, maxValue, templatW, templatH); cvRectangle(srcResult, new_minLoc, cvPoint(new_minLoc.x + templatW, new_minLoc.y+ templatH), cvScalar(0,0,255)); cvNamedWindow("srcResult", 0); cvNamedWindow("templat", 0); cvShowImage("srcResult", srcResult); cvShowImage("templat", templat); cvWaitKey(0); cvReleaseImage(&result); cvReleaseImage(&templat); cvReleaseImage(&srcResult); cvReleaseImage(&src); return 0; }
作者:小村长 出处:http://blog.csdn.net/lu597203933 欢迎转载或分享,但请务必声明文章出处。 (新浪微博:小村长zack, 欢迎交流!)