opencv的matchTemplate函数是对整幅图片进行运算,运算量较大。本文接上篇内容,即:
http://blog.csdn.net/qq_15947787/article/details/55260002
对于SURF目标检测中的多目标,通过鼠标左键单击事件,获得点击的图像坐标,计算当前图像中检测到的离点击位置最近的目标作为模版。
上篇中提到了动态背景下运动目标的检测,但是SURF运算量较大,也并不能做为跟踪使用,因此打算采用模版匹配进行跟踪,为了提高跟踪速度以及准确性,将上一帧图片检测到的目标作为模版,邻域面积的大小为模版面积大小的mul*mul倍。
于是编写了matchTemplateROI函数
image为待寻找目标的图像,而templ是上一帧图像中的目标,即模版,templpos即模版的位置以及大小,函数调用结束后,templ与templpos更新,再次读入下一帧图片,即可。
//************************************
// Description: 模版匹配,在ROI区域中寻找templ,并可迭代
// Method: matchTemplateROI
// FullName: matchTemplateROI
// Access: public
// Parameter: Mat & image 下一帧图像
// Parameter: Mat & templ 上一帧图像中的模版,函数调用结束后为下一帧图像中的模版
// Parameter: Rect & templpos 上一帧图像中模版的位置以及大小,函数调用结束后为下一帧图像中模版的位置以及大小
// Parameter: float mul 邻域边长与模版变长的倍数,大于1
// Returns: void
// Author: 小白
// Date: 2017/02/23
// History:
//************************************
void matchTemplateROI(Mat& image, Mat& templ, Rect& templpos, float mul)
{
//! type of the template matching operation
//enum { TM_SQDIFF=0, TM_SQDIFF_NORMED=1, TM_CCORR=2, TM_CCORR_NORMED=3, TM_CCOEFF=4, TM_CCOEFF_NORMED=5 };
//! computes the proximity map for the raster template and the image where the template is searched for
//CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ, OutputArray result, int method );
Rect ROI;
ROI.x = templpos.x - (templpos.width * mul - templpos.width)/2;
ROI.y = templpos.y - (templpos.height * mul - templpos.height)/2;
ROI.width = templpos.width * mul;
ROI.height = templpos.height * mul;
Mat linyu(image, ROI);//邻域
int Wresult, Hresult;
Wresult = linyu.cols - templ.cols + 1;
Hresult = linyu.rows - templ.rows + 1;
Mat result;//matchTemplate的输出 OutputArray result
result.create(Wresult, Hresult, CV_32FC1);
matchTemplate(linyu, templ, result, TM_SQDIFF_NORMED);
double minVal, maxVal;
Point minLoc, maxLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
templpos.x = minLoc.x + ROI.x;
templpos.y = minLoc.y + ROI.y;
templ = image(templpos);
rectangle(image, Point(ROI.x, ROI.y), Point(ROI.x + ROI.width, ROI.y + ROI.height), Scalar(255,0,0), 2, 8, 0);
rectangle(image, Point(minLoc.x + ROI.x, minLoc.y + ROI.y), Point(minLoc.x + templpos.width + ROI.x, minLoc.y + templpos.height + ROI.y),Scalar(0,0,255), 2, 8, 0);
imshow("image", image);
}
上面蓝框是搜索的邻域,红框是在邻域中找到的目标,也可以换一种方式绘制找到的目标位置。
int s = 15;
if (minLoc.x + ROI.x + templpos.width/2 - 1.5 * s > 0 && minLoc.y + ROI.y + templpos.height/2 - 1.5 * s > 0 && minLoc.x + ROI.x + templpos.width/2 + 1.5 * s < image.cols && minLoc.y + ROI.y + templpos.height/2 + 1.5 * s < image.rows)
{
rectangle(image, Point(minLoc.x + ROI.x + templpos.width/2 - s, minLoc.y + ROI.y + templpos.height/2 - s), Point(minLoc.x + ROI.x + templpos.width/2 + s, minLoc.y + ROI.y + templpos.height/2 + s), Scalar(0,0,255), 1, 8, 0);
line(image, Point(minLoc.x + ROI.x + templpos.width/2, minLoc.y + ROI.y + templpos.height/2 - 1.5 * s), Point(minLoc.x + ROI.x + templpos.width/2, minLoc.y + ROI.y + templpos.height/2 - 0.5 * s), Scalar(0,0,255), 1, 8, 0);
line(image, Point(minLoc.x + ROI.x + templpos.width/2 - 1.5 * s, minLoc.y + ROI.y + templpos.height/2), Point(minLoc.x + ROI.x + templpos.width/2 - 0.5 * s, minLoc.y + ROI.y + templpos.height/2), Scalar(0,0,255), 1, 8, 0);
line(image, Point(minLoc.x + ROI.x + templpos.width/2, minLoc.y + ROI.y + templpos.height/2 + 1.5 * s), Point(minLoc.x + ROI.x + templpos.width/2, minLoc.y + ROI.y + templpos.height/2 + 0.5 * s), Scalar(0,0,255), 1, 8, 0);
line(image, Point(minLoc.x + ROI.x + templpos.width/2 + 1.5 * s, minLoc.y + ROI.y + templpos.height/2), Point(minLoc.x + ROI.x + templpos.width/2 + 0.5 * s, minLoc.y + ROI.y + templpos.height/2), Scalar(0,0,255), 1, 8, 0);
}
替换上面的两个画矩形语句。