C++实现单⽬标跟踪+画出轨迹-OpenCV函数调⽤测试
环境:OpenCV 4.2.0 / OpenCV-contrib 4.2.0 / Visual studio 2017
本以为OpenCV没有封装好的⽬标跟踪算法,然后前⼏天⼀直去各种算法的源码,但是也不亏,算是装了⼀万遍OpenCV的环境了解了下不同版本OpenCV吧,┑( ̄Д  ̄)┍
然后发现居然在OpenCV只是需要调⼀⾏代码的事情:
Ptr<Tracker> tracker;
tracker = TrackerBoosting::create();
tracker = TrackerMIL::create();
tracker = TrackerKCF::create();
tracker = TrackerTLD::create();
tracker = TrackerMedianFlow::create();
tracker = TrackerMOSSE::create();
tracker = TrackerCSRT::create();
没错,就是这么简单。
然后写了⼀段⼩程序测试这些代码。利⽤不同视频。以下是代码:
#include <opencv2/opencv.hpp>
#include <opencv2/tracking.hpp>
#include <opencv2/core/ocl.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat frame;
Rect2d roi;
// Create a tracker 创建跟踪器
Ptr<Tracker> tracker;
//跟踪算法类型
//string trackerTypes[7] = { "BOOSTING", "MIL", "KCF", "TLD","MEDIANFLOW", "MOSSE", "CSRT" };
string videoName;
while (true)
{
while (true)
{
cout << "\n\n------------------------------------------------------------------\n";
cout << "\n\n>> 可测试算法有 BOOSTING MIL KCF TLD MEDIANFLOW MOSSE CSRT"
"\n>> 请输⼊要测试的算法并按回车,退出输⼊exit。"
"\n>> ";
string trackerType;
cin >> trackerType;
if (trackerType == "exit")
{
return 0;
}
if (trackerType == "BOOSTING")
{
tracker = TrackerBoosting::create();
m35cout << "\n>> 选择BOODSTING成功!\n"; break;
}
else if (trackerType == "MIL")
{
tracker = TrackerMIL::create();
cout << "\n>> 选择MIL成功!\n";
break;
}
else if (trackerType == "KCF")
{
tracker = TrackerKCF::create();
cout << "\n>> 选择KCF成功!\n";
break;
}
else if (trackerType == "TLD")
{
tracker = TrackerTLD::create();
cout << "\n>> 选择TLD成功!\n";
break;
}
else if (trackerType == "MEDIANFLOW")
{
tracker = TrackerMedianFlow::create();
cout << "\n>> 选择MEDIANFLOW成功!\n"; break;
}
else if (trackerType == "MOSSE")
{
tracker = TrackerMOSSE::create();
cout << "\n>> 选择MOSSE成功!\n";
break;
}
else if (trackerType == "CSRT")
{
tracker = TrackerCSRT::create();
cout << "\n>> 选择CSRT成功!\n";
break;
}
else
{
cout << "\n>> 选择失败\n";
continue;
}
}
while (true)
{
cout << "\n +--------------+"
"\n | 1.步⾏的⼈_1 |"
"\n | 2.步⾏的⼈_2 |"
"\n | 3.步⾏的⼈_3 |"
"\n | 4.车 |"
"\n | 5.超车 |"
"\n | 6.⼤卫 |"
"\n | 7.跳绳 |"
"\n | 8.摩托越野 |"
"\n | 8.摩托越野 |"
"\n | 9.熊猫 |"
"\n | 10.⼤众汽车 |"
"\n +--------------+"
"\n\n>> 请输⼊要播放视频的序列号(例如4)" "\n>> ";
int videoNo;
cin >> videoNo;
if (videoNo == 1)
奔驰slr722多少钱速腾1.6自动油耗{
videoName = "pedestrian1.mpg";
cout << "\n>> 选择《步⾏的⼈ 1》成功!";
break;
}
else if (videoNo == 2)
{
videoName = "pedestrian2.mpg";
cout << "\n>> 选择《步⾏的⼈ 2》成功!";
break;
}
else if (videoNo == 3)
{
videoName = "pedestrian3.mpg";
cout << "\n>> 选择《步⾏的⼈ 3》成功!";
break;
}
else if (videoNo == 4)
{
videoName = "car.mpg";
cout << "\n>> 选择《车》成功!";
break;
}
else if (videoNo == 5)
{
videoName = "carchase.mpg";
cout << "\n>> 选择《超车》成功!";
break;
}
else if (videoNo == 6)
{
videoName = "david.mpg";
cout << "\n>> 选择《⼤卫》成功!";
break;
}
else if (videoNo == 7)
{
videoName = "jumping.mpg";
cout << "\n>> 选择《跳绳》成功!";
break;
}
else if (videoNo == 8)克莱斯勒跑车
{
videoName = "motocross.mpg";
cout << "\n>> 选择《摩托越野》成功!";
break;
}
else if (videoNo == 9)
{
videoName = "panda.mpg";
cout << "\n>> 选择《熊猫》成功!";
break;
}
else if (videoNo == 10)
{
{
videoName = "volkswagen.mpg";黑豹微卡
cout << "\n>> 选择《⼤众汽车》成功!";
break;
}
else
{
cout << "\n>> 序列号错误,请重新输⼊!";
continue;
}
}
// Read video 读视频
VideoCapture video("D:\\targetTracking\\tracking\\datasets\\" + videoName);
// Exit if video is not opened 如果没有视频⽂件
if (!video.isOpened())
{
cout << "\n>> 读取视频失败";
continue;
}
cout << "\n +----------------------------+"
"\n | 点击 c 逐帧播放视频 |"
"\n | 点击 q 开始选择⽬标 |"
"\n | 点击空格开始播放并追踪⽬标 |"
"\n | 播放期间按q退出播放 |"
"\n +----------------------------+\n";
video >> frame;
//! [getframe]
//added by Ujig
while (1)
{
char key = waitKey(1);
if (key == 'c') // 按c键跳帧
{
video >> frame;
}
if (key == 'q') // 按q键退出跳帧
{
break;
太原汽车租赁}
imshow("Tracking", frame);
}
cv::destroyWindow("Tracking");
//end added
//! [selectroi]选择⽬标roi以GUI的形式
roi = selectROI("tracker", frame);
//! [selectroi]
//quit if ROI was not selected
if (roi.width == 0 || roi.height == 0)
return 0;
// initialize the tracker
//! [init]
tracker->init(frame, roi);
//! [init]
printf("\n>> 开始播放\n");
for (;; ) {
// get frame from the video
video >> frame;
video >> frame;
/
/ stop the program if no more images
if (ws == 0 || ls == 0)
break;
// update the tracking result
//! [update]
tracker->update(frame, roi);
//! [update]
//! [visualization]
// draw the tracked object
rectangle(frame, roi, Scalar(255, 0, 0), 2, 1);
// show image with the tracked object
imshow("tracker", frame);
//! [visualization]
if (char(waitKey(1)) == 'q') {
break;
}
}
cv::destroyWindow("tracker");
cout << ">> 播放完毕\n";
}
return 0;
}
但是这么做有个问题,因为这⾥是将视频逐帧读取、处理并播放的,所以有些算法帧和帧之间的间隔太短,有些太长,所以播出来的视频要么过快,要么过慢。⽽且只⽤⼀句话实现,不加其他处理的话,效果很差,⽬前感觉效果最好的就是TLD算法,但是不排除改进以后结果不⼀样。那么问题来了,TLD原作者更推荐CMT,那么到底是TLD好还是CMT好?
为了实现读取摄像头并跟踪摄像头中的⽬标,改进了代码。实际⽅式是,读取摄像头,先让他正常播放,并等待空格输⼊,直到获取空格输⼊之后截取当下的帧,并进⾏⽬标截取,然后按空格继续,之后可以按q退出程序。
#include <opencv2/opencv.hpp>
#include <opencv2/tracking.hpp>
#include <opencv2/core/ocl.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat frame;
Rect2d roi;
// Create a tracker 创建跟踪器
Ptr<Tracker> tracker;
//跟踪算法类型
//string trackerTypes[7] = { "BOOSTING", "MIL", "KCF", "TLD","MEDIANFLOW", "MOSSE", "CSRT" };
string videoName;
while (true)
{
while (true)
{
cout << "\n\n------------------------------------------------------------------\n";
cout << "\n\n>> 可测试算法有 BOOSTING MIL KCF TLD MEDIANFLOW MOSSE CSRT"
"\n>> 请输⼊要测试的算法并按回车,退出输⼊exit。"
"\n>> ";
string trackerType;
发布评论