OpenTracker指标对比输出
关于OpenTracker的编译安装参考我的上一篇文章目标跟踪实践笔记三。这一篇是我自己在项目源码的基础上进行一些输出显示的修改,来对比显示各个跟踪器的指标。
1、编译trackerscompare
make all
sudo make install
./trackerscompare.bin
在执行最后一步的时候我出现了问题,
./trackerscompare.bin: error while loading shared libraries: libopencv_tracking.so.3.4: cannot open shared object file: No such file or directory
解决办法:
sudo /bin/bash -c 'echo "/usr/local/lib" > /etc/ld.so.conf.d/opencv.conf'
sudo ldconfig
然后重新执行 trackerscompare 的编译即可。
2、浏览 trackerscompare.cpp 文件
打开文件可以看出来,项目提供了三个跟踪图像的来源,openpose(网络摄像头)、video(本地的视频)、datasets(图像数据集)。自己可以根据自己的条件来进行选择。像我虽然最后是需要放在无人机上进行目标识别跟踪,但得先在数据集上验证好才能跑视频流,所以就用最后一个,也是这里的默认选项。
提示:Ubuntu下用自己的USB摄像头跑的话,将72 - 79行程序注释掉,增加以下程序:
cv::Rect2f bboxGroundtruth;
cv::Mat frame, frameDraw;
cv::VideoCapture capture;
VideoCapture capture(0); // open the default camera
if (!capture.isOpened()) // check if we succeeded
return -1;
capture.set(CV_CAP_PROP_FRAME_WIDTH, 1280); //设置分辨率
capture.set(CV_CAP_PROP_FRAME_HEIGHT, 720);
capture >> frame;
frameDraw.copyTo(frame);
std::string window_name = "OpenTracker";
cv::namedWindow(window_name);
//ReadVideo readvideo;
//readvideo.IniRead(bboxGroundtruth, frameDraw, window_name, capture);
同时注释掉 241行 readdatasets.ReadNextFrame(bboxGroundtruth, frame);
打开 243 - 245 行内容
capture >> frame;
if (frame.empty())
return false;
出来图像之后需要自己用鼠标选择目标物,然后就会自动跟踪了。
这个流程其实很类似ECO的流程,都是第一帧先从Groundtruth里面选择跟踪的目标物,然后跑自己的算法。这里对比了OpenCV自带的一些算法、KCF、DSST、ECO几个跟踪算法。实际测试来看OpenCV内部带的明显没有后面三个好,我也把这个删了。
3、更改trackercompare.cpp,输出各算法对比指标
这个文件没有输出相关的指标,只是直观的看一下,所以我才对文件进行一些改动,改动后的程序能够在终端显示出三个跟踪算法的Precision、Iou、SuccessRate 以及 ECO 的 AvgFps。
因为需要用到一些计算,可以直接调用 eco / metrics.cc
文件中的函数,需要改 makefile 文件,在27行后面加上eco/metrics.o\
,最后的程序是这样的:
OBJS=kcf/fhog.o \
kcf/kcftracker.o \
eco/ffttools.o \
eco/fhog.o \
eco/interpolator.o \
eco/optimize_scores.o \
eco/regularization_filter.o \
eco/feature_extractor.o \
eco/feature_operator.o \
eco/training.o \
eco/sample_update.o \
eco/scale_filter.o \
eco/eco.o \
eco/metrics.o\ //加上这个
inputs/readdatasets.o inputs/readvideo.o
TARGET_LIB = libopentracker.so
最后的tarckerscomper.cpp文件内容如下:
#include "kcf/kcftracker.hpp"
#include "eco/eco.hpp"
#include "eco/parameters.hpp"
#include "eco/metrics.hpp" //Add
#ifdef USE_CAFFE
#include "goturn/network/regressor.h"
#include "goturn/tracker/tracker.h"
#endif
#include "inputs/readdatasets.hpp"
#include "inputs/readvideo.hpp"
//#include "inputs/openpose.hpp"
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <opencv2/opencv.hpp>
#include <opencv2/tracking.hpp>
#include <opencv2/core/ocl.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <fstream>
#include <string>
using namespace cv;
using namespace std;
// Convert to string
int main(int argc, char **argv)
{
// Database settings Now only Demo can work
string databaseTypes[5] = {"Demo","VOT-2017", "TB-2015", "TLP", "UAV123"};
string databaseType = databaseTypes[0]; //chose one databaseType
// Set the index of target KCF ====================================================
std::vector<float> KCFCenterError;
std::vector<float> KCFIou;
std::vector<float> KCFFpsEco;
float KCFSuccessRate = 0.0f;
float KCFAvgPrecision = 0.0f;
float KCFAvgIou = 0.0f;
float KCFAvgFps = 0.0f;
//Set the index of target DSST ====================================================
std::vector<float> DSSTCenterError;
std::vector<float> DSSTIou;
std::vector<float> DSSTFpsEco;
float DSSTSuccessRate = 0.0f;
float DSSTAvgPrecision = 0.0f;
float DSSTAvgIou = 0.0f;
float DSSTAvgFps = 0.0f;
//Set the index of target ECO ====================================================
std::vector<float> ECOCenterError;
std::vector<float> ECOIou;
std::vector<float> ECOFpsEco;
float ECOSuccessRate = 0.0f;
float ECOAvgPrecision = 0.0f;
float ECOAvgIou = 0.0f;
float ECOAvgFps = 0.0f;
//metrics is computing toll
Metrics metrics;
int f, isLost;
float x, y, w, h;
std::string s;
std::string path;
ifstream *groundtruth;
ostringstream osfile;
if (databaseType == "Demo")
{
path = "sequences/Crossing";
// some of the dataset has '\t' as the delimiter, change it to ','.
fstream gt(path + "/groundtruth_rect.txt");
string tmp;
size_t index = 1;
while (gt >> tmp)
{
if(tmp.find(',')<10)
{
break;
}
if (index%4 == 0)
{
}
else
{
gt << ",";
}
index++;
}
gt.close();
// Read the groundtruth bbox
groundtruth = new ifstream(path + "/groundtruth_rect.txt");
f = 1;
getline(*groundtruth, s, ',');
x = atof(s.c_str());
getline(*groundtruth, s, ',');
y = atof(s.c_str());
getline(*groundtruth, s, ',');
w = atof(s.c_str());
getline(*groundtruth, s);
h = atof(s.c_str());
cout << f << " " << x << " " << y << " " << w << " " << h << " " << endl;
// Read images in a folder
osfile << path << "/img/" << setw(4) << setfill('0') << f << ".jpg";
cout << osfile.str() << endl;
}
Rect2f bboxGroundtruth(x, y, w, h);
cv::Mat frame = cv::imread(osfile.str().c_str(), CV_LOAD_IMAGE_UNCHANGED);
cv::Mat frameDraw;
frame.copyTo(frameDraw);
if (!frame.data)
{
cout << "Could not open or find the image" << std::endl;
return -1;
}
// Draw gt;
if (databaseType == "Demo")
{
rectangle(frameDraw, bboxGroundtruth, Scalar(0, 0, 0), 2, 1);
}
// Init the trackers=================================================
// Create KCFTracker:
bool HOG = true, FIXEDWINDOW = true, MULTISCALE = true, LAB = true, DSST = false; //LAB color space features
kcf::KCFTracker kcftracker(HOG, FIXEDWINDOW, MULTISCALE, LAB, DSST);
Rect2d kcfbbox((int)x, (int)y, (int)w, (int)h);
kcftracker.init(frame, kcfbbox);
// Create DSSTTracker:
DSST = true;
kcf::KCFTracker dssttracker(HOG, FIXEDWINDOW, MULTISCALE, LAB, DSST);
Rect2d dsstbbox((int)x, (int)y, (int)w, (int)h);
dssttracker.init(frame, dsstbbox);
#ifdef USE_CAFFE
// Create GOTURN tracker:
const string model_file = "goturn/nets/deploy.prototxt";
const string pretrain_file = "goturn/nets/goturun_tracker.caffemodel";
int gpu_id = 0;
Regressor regressor(model_file, pretrain_file, gpu_id, false);
goturn::Tracker goturntracker(false);
cv::Rect goturnbbox(x, y, w, h);
BoundingBox bbox_gt;
BoundingBox bbox_estimate_uncentered;
bbox_gt.getRect(goturnbbox);
goturntracker.Init(frame, bbox_gt, ®ressor);
#endif
// Create ECO trakcer;
eco::ECO ecotracker;
Rect2f ecobbox(x, y, w, h);
eco::EcoParameters parameters;
//parameters.max_score_threshhold = 0.5;
// when use cn feature:
parameters.useCnFeature = false; //false or true is all ok
parameters.cn_features.fparams.tablename = "/usr/local/include/opentracker/eco/look_tables/CNnorm.txt";
ecotracker.init(frame, ecobbox, parameters);
while (frame.data)
{
frame.copyTo(frameDraw);
//KCF=========================
double timerkcf = (double)getTickCount();
bool okkcf = kcftracker.update(frame, kcfbbox);
float fpskcf = getTickFrequency() / ((double)getTickCount() - timerkcf);
if (okkcf)
{
rectangle(frameDraw, kcfbbox, Scalar(0, 255, 0), 2, 1);
}
else
{
putText(frameDraw, "Kcf tracking failure detected", cv::Point(10, 80), FONT_HERSHEY_SIMPLEX,
0.75, Scalar(0, 255, 0), 2);
cout << "Kcf tracking failure detected!" << std::endl;
}
//DSST========================
double timerdsst = (double)getTickCount();
bool okdsst = dssttracker.update(frame, dsstbbox);
float fpsdsst = getTickFrequency() / ((double)getTickCount() - timerdsst);
if (okdsst)
{
rectangle(frameDraw, dsstbbox, Scalar(0, 0, 255), 2, 1); //red
}
else
{
putText(frameDraw, "DSST tracking failure detected", cv::Point(10, 110), FONT_HERSHEY_SIMPLEX,
0.75, Scalar(0, 0, 255), 2);
cout << "DSST tracking failure detected!" << std::endl;
}
#ifdef USE_CAFFE
//GOTURN=====================
double timergoturn = (double)getTickCount();
goturntracker.Track(frame, ®ressor, &bbox_estimate_uncentered);
bbox_estimate_uncentered.putRect(goturnbbox);
float fpsgoturn = getTickFrequency() / ((double)getTickCount() - timergoturn);
rectangle(frameDraw, goturnbbox, Scalar(255, 255, 0), 2, 1);
#endif
//ECO========================
double timeeco = (double)getTickCount();
bool okeco = ecotracker.update(frame, ecobbox);
float fpseco = getTickFrequency() / ((double)getTickCount() - timeeco);
if (okeco)
{
rectangle(frameDraw, ecobbox, Scalar(255, 0, 255), 2, 1);
}
else
{
putText(frameDraw, "ECO tracking failure detected", cv::Point(10, 140), FONT_HERSHEY_SIMPLEX,
0.75, Scalar(255, 0, 255), 2);
cout << "ECO tracking failure detected!" << std::endl;
}
// Display FPS on frameDraw
ostringstream os;
os << float(fpseco);
putText(frameDraw, "FPS: " + os.str(), Point(100, 30), FONT_HERSHEY_SIMPLEX,
0.75, Scalar(255, 0, 255), 2);
// Draw the label of trackers
putText(frameDraw, "KCF ", cv::Point(frameDraw.cols - 180, 75), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 255, 0), 2);
line(frameDraw, cv::Point(frameDraw.cols - 100, 75), cv::Point(frameDraw.cols - 10, 75), Scalar(0, 255, 0), 2, 1);
putText(frameDraw, "DSST ", cv::Point(frameDraw.cols - 180, 100), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2);
line(frameDraw, cv::Point(frameDraw.cols - 100, 100), cv::Point(frameDraw.cols - 10, 100), Scalar(0, 0, 255), 2, 1);
putText(frameDraw, "ECO ", cv::Point(frameDraw.cols - 180, 125), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(255, 0, 255), 2);
line(frameDraw, cv::Point(frameDraw.cols - 100, 125), cv::Point(frameDraw.cols - 10, 125), Scalar(255, 0, 255), 2, 1);
#ifdef USE_CAFFE
putText(frameDraw, "GOTURN ", cv::Point(frameDraw.cols - 180, 150), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(255, 255, 0), 2);
line(frameDraw, cv::Point(frameDraw.cols - 100, 150), cv::Point(frameDraw.cols - 10, 150), Scalar(255, 255, 0), 2, 1);
#endif
// Display frameDraw
imshow("OpenTracker", frameDraw);
int c = cvWaitKey(1);
if (c != -1)
c = c % 256;
if (c == 27)
{
cvDestroyWindow("OpenTracker");
return 0;
}
waitKey(1);
// Read the next frame======================================================
// cout << "Frame:" << f << " FPS:" << fpseco << endl;
f++;
osfile.str("");
if (databaseType == "Demo")
{
getline(*groundtruth, s, ',');
x = atof(s.c_str());
getline(*groundtruth, s, ',');
y = atof(s.c_str());
getline(*groundtruth, s, ',');
w = atof(s.c_str());
getline(*groundtruth, s);
h = atof(s.c_str());
//cout << f << " " << x << " " << y << " " << w << " " << h << " " << isLost << endl;
// Read images in a folder
osfile << path << "/img/" << setw(4) << setfill('0') << f << ".jpg";
//cout << osfile.str() << endl;
}
bboxGroundtruth.x = x;
bboxGroundtruth.y = y;
bboxGroundtruth.width = w;
bboxGroundtruth.height = h;
frame = cv::imread(osfile.str().c_str(), CV_LOAD_IMAGE_UNCHANGED);
if(!frame.data)
{
break;
}
// Calculate the metrics;
// KCF index ===========================================================
float kcfcentererror = metrics.center_error(kcfbbox, bboxGroundtruth);
float kcfiou = metrics.iou(kcfbbox, bboxGroundtruth);
KCFCenterError.push_back(kcfcentererror);
KCFIou.push_back(kcfiou);
// KCFFpsEco.push_back(fpseco);
if(kcfcentererror <= 20)
{
KCFAvgPrecision++;
}
if(kcfiou >= 0.5)
{
KCFSuccessRate++;
}
//DSST index =============================================================
float dsstcentererror = metrics.center_error(dsstbbox, bboxGroundtruth);
float dsstiou = metrics.iou(dsstbbox, bboxGroundtruth);
DSSTCenterError.push_back(dsstcentererror);
DSSTIou.push_back(dsstiou);
// DSSTFpsEco.push_back(fpseco);
if(dsstcentererror <= 20)
{
DSSTAvgPrecision++;
}
if(dsstiou >= 0.5)
{
DSSTSuccessRate++;
}
// ECO index ============================================================
float ecocentererror = metrics.center_error(ecobbox, bboxGroundtruth);
float ecoiou = metrics.iou(ecobbox, bboxGroundtruth);
ECOCenterError.push_back(ecocentererror);
ECOIou.push_back(ecoiou);
ECOFpsEco.push_back(fpseco);
if(ecocentererror <= 20)
{
ECOAvgPrecision++;
}
if(ecoiou >= 0.5)
{
ECOSuccessRate++;
}
}
#ifdef USE_MULTI_THREAD
void *status;
int rc = pthread_join(ecotracker.thread_train_, &status);
if (rc)
{
cout << "Error:unable to join," << rc << std::endl;
exit(-1);
}
#endif
cout << std::endl;
cout << std::endl;
cout << "Frames:" << f - 2 << std::endl << std::endl;
//Cout KCF
KCFAvgPrecision /= (float)(f - 2);
KCFSuccessRate /= (float)(f - 2);
KCFAvgIou = std::accumulate(KCFIou.begin(), KCFIou.end(), 0.0f) / KCFIou.size();
// KCFAvgFps = std::accumulate(FpsEco.begin(), FpsEco.end(), 0.0f) / FpsEco.size();
cout << "KCF result:"
<< "\tKCFAvgPrecision: " << KCFAvgPrecision //Mean Average Precission
<< "\tKCFAvgIou: " << KCFAvgIou
<< "\tKCFSuccessRate: " << KCFSuccessRate
<< std::endl << std::endl;
//Cout DSST
DSSTAvgPrecision /= (float)(f - 2);
DSSTSuccessRate /= (float)(f - 2);
DSSTAvgIou = std::accumulate(DSSTIou.begin(), DSSTIou.end(), 0.0f) / DSSTIou.size();
// KCFAvgFps = std::accumulate(FpsEco.begin(), FpsEco.end(), 0.0f) / FpsEco.size();
cout << "DSST result:"
<< "\tDSSTAvgPrecision: " << DSSTAvgPrecision //Mean Average Precission
<< "\tDSSTAvgIou: " << DSSTAvgIou
<< "\tDSSTSuccessRate: " << DSSTSuccessRate
<< std::endl << std::endl;
//Cout ECO
ECOAvgPrecision /= (float)(f - 2);
ECOSuccessRate /= (float)(f - 2);
ECOAvgIou = std::accumulate(ECOIou.begin(), ECOIou.end(), 0.0f) / ECOIou.size();
ECOAvgFps = std::accumulate(ECOFpsEco.begin(), ECOFpsEco.end(), 0.0f) / ECOFpsEco.size();
cout << "ECO result:"
<< "\tECOAvgPrecision: " << ECOAvgPrecision //Mean Average Precission
<< "\tECOAvgIou: " << ECOAvgIou
<< "\tECOSuccessRate: " << ECOSuccessRate
<< "\tECOAvgFps: "<< ECOAvgFps
<< std::endl << std::endl;
cvDestroyWindow("OpenTracker");
return 0;
}
4、算法不足的分析及改进
未完待续