@转载请注明出处
模板匹配跟踪:
1.鼠标标记初始目标位置,并初始化模板
2.每一帧在上一帧匹配出来的位置附近搜索,可以加快速度。
3.加入丢失阈值判断,当丢失的时候不画波门。
主要应用opencv模板匹配api:
CV_EXPORTS_W void matchTemplate( InputArray image, InputArray templ,
OutputArray result, int method );
完整代码如下:
/*created at 2019/7/22 0:20*/
#include <iostream>
#include <opencv2/opencv.hpp>
static cv::Rect roi;
void drawLine(cv::Mat src, cv::Rect& res);
static bool drawflag = false;
void setMouse(int event, int x, int y, int flag, void* param)
{
cv::Mat* image = (cv::Mat*)param;
cv::Point p1, p2;
switch(event)
{
case CV_EVENT_LBUTTONDOWN:
drawflag = true;
roi.x = x;
roi.y = y;
break;
case CV_EVENT_MOUSEMOVE:
p1 = cv::Point(roi.x, roi.y);
p2 = cv::Point (x, y);
if(drawflag)
cv::rectangle(*image, p1, p2, cv::Scalar(255,0,0));
break;
case CV_EVENT_LBUTTONUP:
roi.width = x - roi.x;
roi.height = y - roi.y;
if(drawflag)
{
drawLine(*image, roi);
std::cout << "get track init rect, x: " << roi.x << "y: " << roi.y \
<< "w: " << roi.width << "h: " << roi.height << std::endl;
drawflag = false;
}
break;
default:
break;
}
}
cv::Mat bgr2gray(cv::Mat src)
{
cv::Mat gray;
if(src.channels() == 3)
cv::cvtColor(src, gray, CV_BGR2GRAY);
else
src.copyTo(gray);
return gray;
}
void drawLine(cv::Mat src, cv::Rect& res)
{
res.x = (res.x < 0 ? 0 : res.x);
res.y = (res.y < 0 ? 0 : res.y);
res.width = (res.width > src.cols ? src.cols : res.width);
res.height = (res.height > src.rows ? src.rows : res.height);
if(res.x + res.width > src.cols)
res.x = src.cols - res.width - 1;
if(res.y + res.height > src.rows)
res.y = src.rows - res.height - 1;
cv::rectangle(src, res, cv::Scalar(255,0,0));
}
bool matchTracker(cv::Mat src, cv::Rect& res, cv::Mat model, int scale, float failed)
{
double maxVal;
cv::Point matchPoint;
cv::Mat model_32F;
cv::Mat searchWindow;
cv::Rect search;
cv::Mat similarity;
//simple check
assert(src.data != NULL);
assert(src.type() == CV_8UC1);
assert(model.rows <= src.rows);
assert(model.cols <= src.cols);
//search window
search.width = scale * res.width;
search.width = (search.width > src.cols ? src.cols : search.width);
search.height = scale * res.height;
search.height = (search.height > src.rows ? src.rows : search.height);
search.x = res.x + 0.5 * res.width - 0.5 * search.width;
if(search.x + search.width > src.cols)
search.x = src.cols - search.width - 1;
search.x = search.x < 0 ? 0 : search.x;
search.y = res.y + 0.5 * res.height - 0.5 * search.height;
if(search.y + search.height > src.rows)
search.y = src.rows - search.height - 1;
search.y = search.y < 0 ? 0 : search.y;
searchWindow = src(search);
searchWindow.convertTo(searchWindow, CV_32F);
model.convertTo(model_32F, CV_32F);
cv::matchTemplate(searchWindow, model_32F, similarity, CV_TM_CCOEFF_NORMED);
cv::minMaxLoc(similarity, NULL, &maxVal, NULL, &matchPoint);
if(maxVal > failed)
{
res.x = search.x + matchPoint.x;
res.y = search.y + matchPoint.y;
return true;
}
return false;
}
int main(int argc, char* argv[])
{
cv::Mat frame, bgr;
cv::VideoCapture cap;
cv::Mat model;
cv::Rect trkRes;
bool flag = true;
const char *path = "vtest.avi";
int key = 0;
std::string windowName = "tracking.jpg";
assert(cap.open(path));
while(cap.read(bgr))
{
frame = bgr2gray(bgr);
if(flag)
{
cv::imshow(windowName, bgr);
cv::Mat copy = bgr.clone();
cv::setMouseCallback(windowName, setMouse, (void*)©);
while(!(key == 32 || key == 27 || key == 13))
{
cv::imshow(windowName, copy);
if(drawflag)
copy = bgr.clone();
key = cv::waitKey(1);
}
model = frame(roi);
trkRes = roi;
flag = false;
continue;
}
else
{
bool state = matchTracker(frame, trkRes, model, 4, 0.5f);
if(state)
drawLine(bgr, trkRes);
else
std::cout << "track lose..." << std::endl;
}
cv::imshow(windowName, bgr);
cv::waitKey(20);
}
cap.release();
return 0;
}
暂时未加入多尺度。下一版本加入。
待续。。。