链接:http://www.opencv.org.cn/opencvdoc/2.3.2/html/modules/imgproc/doc/object_detection.html?highlight=matchtemplate#cv.MatchTemplate
matchTemplate(InputArray image, InputArray temp, OutputArray result, int method)
Parameters: |
|
---|
第一个参数为输入源图像,第二个参数为输入模板图像,第三个参数为匹配结果,记录在源图像上滑动窗口和模板的相似程度,第四个参数为匹配方法。
匹配方法:
CV_TM_SQDIEF平方差匹配法,最好匹配为0,值越大匹配越差
CV_TM_SQDIEF_NORMED归一化平方差匹配法
CV_TM_CCORR相关匹配法,采用乘法操作,数值越大表明匹配越好
CV_TM_CCORR_NORMED归一化相关匹配法
CV_TM_CCOEFF相关系数匹配法,最好匹配为1,最差为-1
CV_TM_CCOEFF_NORMED归一化相关系数匹配法
各匹配方法原理见以上链接。
链接:http://www.opencv.org.cn/opencvdoc/2.3.2/html/modules/core/doc/operations_on_arrays.html?highlight=minmaxloc#cv.MinMaxLoc
minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArraymask=noArray())
Parameters: |
|
---|
寻找矩阵中最大最小值以及对应坐标。
原图:
模板图像:
代码如下:
#include "stdafx.h" #include "cv.h" #include "highgui.h" #include "cxcore.h" using namespace std; using namespace cv; int _tmain(int argc, _TCHAR* argv[]) { Mat img,templ,result; img = imread("1.jpg"); templ = imread("2.jpg"); int result_cols = img.cols - templ.cols + 1; int result_rows = img.rows - templ.rows + 1; result.create(result_cols, result_rows, CV_32FC1); matchTemplate(img, templ, result, CV_TM_SQDIFF_NORMED);//CV_TM_SQDIFF_NORMED CV_TM_SQDIFF normalize(result, result, 0, 1, NORM_MINMAX, -1, Mat()); double minVal; double maxVal; Point minLoc; Point maxLoc; Point matchLoc; minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat()); matchLoc = minLoc; rectangle(img, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), Scalar(0,255,0), 2, 8, 0); imshow("img", img); waitKey(0); return 0; }
效果如下:
由于采用鼠标画矩形框的方式进行模板图像的提取,所以对鼠标响应函数进行说明。
cvSetMouseCallback(const char* name, CvMouseCallback onMouse, void* param=NULL )
Parameters: |
|
---|
第一个参数为使用窗口名,第二个为onMouse鼠标消息消息处理函数,第三个为传给鼠标消息的任定参数。
这里添加onMouse函数如下:
void onMouse(int event,int x,int y,int flags,void*param)//事件回传代号,坐标,代号,Mouse事件的代号名称 { if (pause) { switch (event) { case CV_EVENT_MOUSEMOVE: if (drawbox){ box.width = x - box.x; box.height = y - box.y; } break; case CV_EVENT_LBUTTONDOWN: drawbox = true; box = Rect(x, y, 0, 0); break; case CV_EVENT_LBUTTONUP: drawbox = false; if (box.width < 0){ box.x += box.width; box.width *= -1; } if (box.height < 0){ box.y += box.height; box.height *= -1; } cvtColor(img,imggray,CV_RGB2GRAY); templ = imggray(box); tracking = true; rectangle(frame, box, Scalar(0, 255, 0), 3); imshow("ORI", frame); imshow("Templ", templ); break; } } }
Event:
#define CV_EVENT_MOUSEMOVE 0 滑動
#define CV_EVENT_LBUTTONDOWN 1 左鍵點擊
#define CV_EVENT_RBUTTONDOWN 2 右鍵點擊
#define CV_EVENT_MBUTTONDOWN 3 中鍵點擊
#define CV_EVENT_LBUTTONUP 4 左鍵放開
#define CV_EVENT_RBUTTONUP 5 右鍵放開
#define CV_EVENT_MBUTTONUP 6 中鍵放開
#define CV_EVENT_LBUTTONDBLCLK 7 左鍵雙擊
#define CV_EVENT_RBUTTONDBLCLK 8 右鍵雙擊
#define CV_EVENT_MBUTTONDBLCLK 9 中鍵雙擊
flags:
#define CV_EVENT_FLAG_LBUTTON 1 左鍵拖曳
#define CV_EVENT_FLAG_RBUTTON 2 右鍵拖曳
#define CV_EVENT_FLAG_MBUTTON 4 中鍵拖曳
#define CV_EVENT_FLAG_CTRLKEY 8 (8~15)按Ctrl不放事件
#define CV_EVENT_FLAG_SHIFTKEY 16 (16~31)按Shift不放事件
#define CV_EVENT_FLAG_ALTKEY 32 (32~39)按Alt不放事件
模板匹配跟踪函数如下:
void track(Mat gray, Mat &templ, Rect &box) { double minVal; double maxVal; Point minLoc; Point maxLoc; matchTemplate(gray, templ, result, CV_TM_SQDIFF); minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, Mat()); matchLoc = minLoc; rectangle(gray, matchLoc, Point(matchLoc.x + templ.cols, matchLoc.y + templ.rows), Scalar(0,0,255), 2, 8, 0); }
GIF效果如下: