武汉加油,中国加油
在家无聊,一开始准备用模板匹配写一个目标追踪,今天逛论坛,发现Opencv自带追踪大法,赶紧运行了一番,发现效果还行,速度快的不要不要的。
但是缺陷也是非常的明显,准确度不敢恭维,非常容易丢目标,误差不断累积,以至于最后越来越不准确,还有就是目标消失后,矩形框会一直存在。
话不多说,直接上代码,注释很详细,不多解释。
其实单目标追踪跟多目标追踪的方法是一样的具体如下,自由发挥。
单目标追踪
#include <opencv2/core/utility.hpp>
#include <opencv2/tracking.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <cstring>
using namespace std;
using namespace cv;
int main(){
Rect2d roi;
Mat frame;
//实例化跟踪器
Ptr<TrackerKCF> tracker = TrackerKCF::create();
//载入视频
string video = "C:\\Users\\14587\\Desktop\\test1.mp4";
VideoCapture cap(video);
//载入摄像头
//VideoCapture cap(0);
if (!cap.isOpened())
{
printf("can not load video");
return 0;
}
cout << "按s进入目标选择" << endl;
cout << "按空格键进入目标追踪" << endl;
cout << "按q退出" << endl;
cap >> frame;
while (1)
{
char key = waitKey(15);
// 按d跳下一帧
cap >> frame;
resize(frame, frame, Size(600, 400));
// 按s进入目标选择
if (key == 's')
{
break;
}
namedWindow("目标选择", WINDOW_NORMAL);
imshow("目标选择", frame);
}
//销毁第一个窗口进入追踪窗口
destroyWindow("目标选择");
//鼠标框选ROL目标
roi = selectROI("tracker", frame);
if (roi.width == 0 || roi.height == 0)
return 0;
//init 初始化最初要跟踪的区域
tracker->init(frame, roi);
//进入追踪
printf("开始追踪\n");
while(cap.read( frame) ){
resize(frame, frame, Size(600, 400));
// 播放完销毁窗口
if (frame.rows == 0 || frame.cols == 0) {
destroyWindow("tracker");
break;
}
// update 有新的数据来之后更新位置
tracker->update(frame, roi);
// 绘制矩形框
rectangle(frame, roi, Scalar(255, 0, 0), 2, 1);
// 窗口显示
imshow("tracker", frame);
waitKey(30);
// q退出
if (char(waitKey(1)) == 'q')
{
destroyWindow("tracker");
break;
}
}
return 0;
}
多目标追踪
#include<opencv2\opencv.hpp>
#include<opencv2\tracking.hpp>
using namespace cv;
using namespace std;
int main(int arc, char** argv)
{
//加载摄像头
//VideoCapture capture(0);
//加载视频文件
VideoCapture capture;
capture.open("C:\\Users\\14587\\Desktop\\test1.mp4");
if (!capture.isOpened())
{
printf("can not load video");
return 0;
}
cout << "按s进入目标选择" << endl;
cout << "按enter/space确定选择" << endl;
cout << "按c取消选择" << endl;
cout << "按esc进入追踪" << endl;
//实例化一个多目标跟踪器的对象
MultiTracker trackers;
Mat frame;
capture.read(frame);
//进入帧目标选择
while (1)
{
char key = waitKey(15);
capture >> frame;
// 按s进入目标选择
if (key == 's')
{
break;
}
//调整视频大小
resize(frame, frame, Size(600, 400));
namedWindow("目标选择", CV_WINDOW_AUTOSIZE);
imshow("目标选择", frame);
}
//鼠标选择目标
resize(frame, frame, Size(600, 400));
vector<Rect> rois;
selectROIs("目标选择", frame, rois, false);
//传入的边界框数据类型是Rect2d,因为涉及到计算,所以需要double类型,需要转换一下。
vector<Rect2d> obj;
vector<Ptr<Tracker>> algorithms;
for (auto i = 0; i < rois.size(); i++)
{
obj.push_back(rois[i]);
algorithms.push_back(TrackerKCF::create());
}
//添加目标
trackers.add(algorithms, frame, obj);
destroyWindow("目标选择");
//进入追踪
while (capture.read(frame))
{
//调整视频大小
resize(frame, frame, Size(600, 400));
//更新目标
trackers.update(frame, obj);
//绘制矩形框
for (auto j = 0; j < obj.size(); j++)
{
rectangle(frame, obj[j], Scalar(255, 0, 0), 2, 1);
}
namedWindow("目标追踪", CV_WINDOW_AUTOSIZE);
imshow("目标追踪", frame);
char c = waitKey(15);
if (c == 27)
{
break;
}
}
waitKey(0);
return 0;
}