环境: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();
cout << "\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 | 9.熊猫 |"
"\n | 10.大众汽车 |"
"\n +--------------+"
"\n\n>> 请输入要播放视频的序列号(例如4)"
"\n>> ";
int videoNo;
cin >> videoNo;
if (videoNo == 1)
{
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;
// stop the program if no more images
if (frame.rows == 0 || frame.cols == 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;
cin >> trackerType;
if (trackerType == "exit")
{
return 0;
}
if (trackerType == "BOOSTING")
{
tracker = TrackerBoosting::create();
cout << "\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;
}
}
cout << "\n>> 输入1选择本地视频进行播放"
"\n>> 输入2选择实时摄像头播放"
"\n>> ";
int judgement;
cin >> judgement;
if (1 == judgement)
{
while (true)
{
cout << "\n +--------------+"
"\n | 1.步行的人_1 |"
"\n | 2.步行的人_2 |"
"\n | 3.步行的人_3 |"
"\n | 4.车 |"
"\n | 5.超车 |"
"\n | 6.大卫 |"
"\n | 7.跳绳 |"
"\n | 8.摩托越野 |"
"\n | 9.熊猫 |"
"\n | 10.大众汽车 |"
"\n +--------------+"
"\n\n>> 请输入要播放视频的序列号(例如4)"
"\n>> ";
int videoNo;
cin >> videoNo;
if (videoNo == 1)
{
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);
//VideoCapture video(0);
// 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]
cout << "\n>> 开始播放\n";
for (;; ) {
// get frame from the video
video >> frame;
// stop the program if no more images
if (frame.rows == 0 || frame.cols == 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]
//added by Ujig
if (char(waitKey(30)) == 'q') {
break;
}
}
cv::destroyWindow("tracker");
cout << ">> 播放完毕\n";
}
else if (2 == judgement)
{
VideoCapture video(0, CAP_DSHOW);
if (!video.isOpened())
{
cout << "\n>> 读取视频失败";
continue;
}
cout << "\n>> 请按空格开始截取图片\n\n";
while (1)
{
video >> frame; //读取当前帧
//若视频完成播放,退出循环
if (frame.empty())
{
cout << "发生错误,请检查摄像头是否已断开!";
break;
}
imshow("tracker", frame); //显示当前帧
if (char(waitKey(30)) == 32) {
break;
}
//waitKey(30); //延时30ms
}
//! [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]
cout << "\n>> 开始播放\n";
cout << "\n>> 如需退出请按q退出播放\n";
for (;; ) {
// get frame from the video
video >> frame;
// stop the program if no more images
if (frame.rows == 0 || frame.cols == 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(30)) == 'q') {
break;
}
}
cv::destroyWindow("tracker");
cout << "\n>> 播放完毕\n";
}
else
{
cout << "输入有误!";
}
}
return 0;
}
测试结果整理:
视频播放:
因为视频播放受限于视频的种类和场景多样化有限的限制,测试结果没有摄像头播放的测试结果那么可靠和多样。但是还是存在一定的可参考意义。
测试视频,汽车行驶,期间会部分车体消失在框内,会被树木挡住等多种意外情况。总长37秒,记录长度的原因是采用每个算法时候播放视频的速度不一样。
测试视频,大卫,大卫从暗处走向明处,测试算法的学习性能和方框会不会根据目标进行自适应变化。视频长度30秒。
测试视频,熊猫,测试视频的学习性能。视频长度119秒。
测试视频,跳绳,测试视频对于快速移动的适应性能。视频长度12秒。
- BOOSTING:
当车体一半移出框的时候方框会留在视频框的边缘,当车辆重新全部车体进入框内时候会重新正常跟踪目标
当车体被树木挡住的时候会出现跟丢目标的情况,车辆重新出现时候方框会失去目标一段时间,并之后的跟踪全都不准。
目标被挡住的时候方框并不会消失。
用时60秒。
从暗处来到明处时候跟踪效果只能说良好,会出现一定程度上的丢失,但是后来能找回来一丢丢。
方框并不能根据目标自适应变化大小。
用时40秒。
对于熊猫的跟踪很好,基本不会出现目标跟丢的情况,熊猫动作角度变化都能进行正确跟踪。
熊猫消失的一段时间方框不消失,当熊猫出现时能重新跟踪熊猫。但是跟踪时候方框的位置比之前稍稍有偏移,但是总体来讲还是能正常跟踪目标。
被树木挡住以后还是能正常跟踪,当相机拉近时候就会丢失目标,并且没法重新找到目标。
用时130秒。
跳绳全程能保持很好的跟踪,有一次出现不明跳动,但是就一瞬间而已。
用时15秒。
- MIL:
当车体一半移出屏幕时候方框会留在视频方框的边缘,当车辆重新进入视频框内时候并不能重新正确定位到目标,而是会保持刚刚在目标的位置。
当车体被树木挡住的时候方框会跟丢目标,车辆重新出现时候方框会失去目标,并无法重新找到目标,有一种要重新找到的趋势,但是终将失败。当目标接近框的时候框能重新找到目标。
目标被挡住的时候方框不会消失。
用时92秒。
从暗处到明处来的时候跟踪效果良好,期间没有出现跟丢情况。只是方框位置稍稍有些偏移。
方框并不能根据目标自适应变化大小。
用时81秒。
对熊猫的跟踪效果挺好,没有出现跟丢的情况,只是方框的位置还是会出现偏移,不在正中间。
当熊猫消失在屏幕的时候方框会在消失的地方等待,并不会消失,当熊猫重新出现时候方框能重新找到目标斌进行跟踪。
当熊猫被树木挡住的时候也能正常跟踪,当镜头拉近的时候方框还是能正常跟踪熊猫。
方框会出现莫名抖动。
用时270秒。
前面一直正常,中间突然丢失目标,并没法重新找到。重新测试一次没有出现丢失情况。
用时30秒。
- KCF:
当车体一半移出屏幕时候方框不会移动,还是会跟着目标一起一半在视频框之外。
当车体被树木挡住的时候方框会跟丢目标,并且没法重新找到。
目标被挡住的时候方框不消失。
用时32秒。
从暗处到明初时候能良好的跟踪目标,但是有时候会丢失,第一次丢失重新找回来了,第二次没能重新找回来。
方框不会根据目标自适应变化大小。
用时30秒。
跟踪熊猫效果不好,当熊猫经过树干的时候就丢失了目标,并保持视频框的相对位置,并没有重新找到目标。
用时100秒。
跳绳开始就跟丢目标,对移动快的目标跟踪不好。并没能重新找到目标。
用时12秒。
- TLD:
当车体一半移出屏幕时候方框会变化大小等待目标,能正常跟踪。
出现表明大小变化抖动。
当车体被树木挡住的时候还是能进行一定程度的正常跟踪,当障碍过去以后还是能重新找到目标。
目标被挡住的时候方框不会消失,能根据部分信息一定程度上找的到目标。
用时43秒。
目标从暗处到明处时候会跟丢目标,亮度的变化会让他丢失目标。
方框大小会变化,但是形状不会变化。
用时39秒。
方框能一定程度上找到目标,但是熊猫只剩一个屁股时候方框会丢失目标,丢失能很快找回目标。
当熊猫消失在视频里的时候方框会去找别的目标,并不会停留在原地,当熊猫回来以后他过了一段时间重新找到了目标。
方框全程出现慕名抖动。
熊猫被树木挡住以后出现找不到的情况,丢失离开树木时候立刻就找到了。
用时140秒。
一定程度上能在一直跟踪目标,但是抖动比较大,大小变化也多。
用时17秒。
- MEDIANFLOW:
当车体一半移出屏幕时候跟踪效果很好,会跟着目标一起一半移出屏幕。
不出现抖动,但是当目标出现很小的遮挡(红绿顶,但是路灯就没事,但是经过路灯会出现一丢丢方框的变化)就会跟丢目标并且方框变得莫名的大。
目标被挡住的时候方框不消失。
用时31秒。
当大卫从暗处到明处来的时候跟踪效果特别好,跟踪效果全程都很好。
会根据目标大小自适应变化大小。
期间没有出现抖动,没有出现跳动。
用时24秒。
当熊猫经过树旁边(那颗树并没有挡到他)就丢似乎了目标。当熊喵重新经过留在原地蒙蔽的框旁边的时候框也不能找回目标。
用时96秒。
刚开始跟踪很好,突然出现框莫名变大的情况,但是还是能跟着目标动。(我猜应该是因为背景的变化的原因。)
用时13秒。
- MOSSE:
当车体一半移出屏幕时候方框能很好的跟随目标,也会跟着目标一起一半移出视频框。
当车体被树木挡住的时候,先前时候比较少的树叶挡住时候能很好跟踪,后来变多时候会丢失目标,并再也找不回来。
目标被挡住的时候方框不会消失。
用时30秒。
当大卫从暗处到明处时候方框能很好的跟随,没有出现丢失目标的情况。
方框不会随着目标大小自适应变化大小。
出现轻微的方框位置不对的情况。
用时30秒。
熊猫移动到会挡住他的细树干后面时候就丢失了目标,并没再能继续跟踪目标。
用时95秒。
跳绳视频开始跟踪了一秒,可能人物脸部变化较大还是怎么样,就不能继续跟踪了。
用时10秒。
- CSRT:
当车体一半移出屏幕时候能很好的跟着目标,并且会跟着目标一起一半部分出视频框。
当车体被树木挡住的时候会试着去寻找,找到的概率不高,当障碍过去以后第一次勉勉强强重新找到了,但是方框位置只是在车的后半段。
目标被挡住的时候方框不会消失。
用时50秒。
当大卫从暗处到明处时候方框能一直保持跟踪,并且跟踪i笑熬过特别好,还能根据目标大小变化大小。只是变化大小的准度不太好。
方框有特别微笑的大小抖动,不影响。
用时41秒。
方框能一直很好的跟踪熊猫,但是偶尔会出现方框位置的偏移。
当熊猫从画面小时以后方框就在消失的地方等着,重新出现以后没能重新跟上目标。
被树叶遮挡以后还能继续跟踪熊猫,但是当相机拉近时候就丢失了目标。
用时144秒。
跳绳的视频一直能很好地跟踪。
用时17秒。
摄像头播放:
- BOOSTING:
能很好的跟踪眼睛,眯眼也能正确识别,抬头转头都可以正确识别,但是低头时候出现了丢失的情况,丢失以后并不会呆在原地,而是跟踪框到的目标(口罩的边缘)。如果转角度让方框重新回到眼睛上他就能继续跟踪。抬头低头时候出现明显的跳动,当恢复正常姿势时候能不能重新找到目标不确定。
斜头时候跟踪效果不错。
抗遮挡不好,用手挡住以后,重新移开手时候找不到眼睛。
快速移动头部他就会丢失目标。
对左眼右眼没有判断力。
并不能跟随目标大小变化大小。 - MIL:
最直观的感觉就是卡!
很容易丢失目标。但是偶尔还不会丢失,很奇怪,眯眼时候也能正常识别。
斜头时候跟踪效果不错。
挡住眼睛之后就会丢失,并不能重新跟踪目标。
头部快速移动时候不能有效跟踪目标。
对左眼右眼没有判断力。
并不能跟随目标大小变化大小。 - KCF:
稍微有点变化就会丢失目标。
斜头时候跟踪效果不好。
不抗遮挡,遮挡之后就会丢失,不会自己去找到目标,之后框会停止在刚刚位置,把眼睛放到框里他会继续跟踪。把另一只眼睛放进去他也会误认为是目标而跟踪。
头部动的较快的话就会丢失目标。
并不能跟随目标大小变化大小。 - TLD:
跟踪效果很好,对抬头,低头,斜头,眯眼等情况识别都很好。
对左眼右眼的判断一般般,偶尔会在两眼之间跳动。
抗遮挡挺好的,当移开手的时候能重新找到目标。
快速移动头部的时候,跟踪效果良好,虽然有时会丢失,但是之后能重新找回来。
方框有莫名的大小变化的抖动。
会根据目标大小改变方框大小。 - MEDIANFLOW:
对目标的跟踪效果很好,对抬头,低头,转头,眯眼,斜头的识别效果都很好。
会随着目标大小自适应变化大小,效果很好。
抗遮挡不太好,一小点消失或者遮挡会造成方框大小莫名变大。
对快速移动的目标识别较好,不会丢失目标,但是会出现方框莫名变大的情况。可能跟遮挡原因是类似的。
没有出现左右眼识别错误的情况。 - MOSSE:
偶尔会出现莫名的目标丢失,此时方框会留在原地,当重新把眼睛放进去以后他会重新找到目标并跟踪。对眯眼,抬头,低头,斜头,转头的识别不错。
对左右眼判断力不高。
有遮挡物,或者移动过快时候会丢失目标,方框停留在原地,当重新把眼睛放到方框里,就能重新识别。放另一只眼睛也会跟踪。
并不能跟随目标大小变化大小。 - CSRT:
能很好的跟踪目标,对抬头,低头,转头,眯眼,斜头都有很好的识别,并且没有丢失。
对左眼右眼的判断能力弱,但是都在的时候会优先选择正确的那只。
抗遮挡能力弱,目标消失之后,不会停留在原地,而是去跟踪别的目标。
不能根据目标大小,自适应变化大小。
对快速移动的目标没有识别能力,有时候慢下来以后能找到目标,有时候不行。
2020.03.25号的更新
好像忘了在博客里更新画出目标移动轨迹的部分代码了,代码如下,将以下代码加在rectangle()方法的下面就可以了,在本地视频和实时摄像头两处都要加。
Point presentPoint;
presentPoint.x = (roi.x + (roi.width*0.5))*2;
presentPoint.y = (roi.y + (roi.height*0.5))*2;
vecPoint.push_back(presentPoint);
if (vecPoint.size() > 1)
{
for (int i = 1; i < vecPoint.size(); i++)
{
line(frame, vecPoint[i - 1], vecPoint[i], Scalar(0, 0, 255), 1, 8, 1);
}
}
因为只有一个目标,所以没必要添加文字标签,如果有必要可以去参考我另一篇多目标跟踪博客里的添加文字标签的方法。