OpenCV跟踪模块算法介绍
OpenCV的tracking模块是一个功能强大的跟踪算法库,包含多种用于跟踪对象的算法。它可以帮助你在连续的视频帧中定位一个物体,例如人脸、眼睛、车辆等。
在OpenCV的tracking模块中,一些主要的跟踪算法包括:
- 稀疏光流(Sparse optical flow):例如Kanade-Lucas-Tomashi (KLT)特征跟踪算法,跟踪图像中几个特征点的位置。
- 卡尔曼滤波(Kalman Filtering):一种非常流行的基于先验运动信息的信号处理算法,用于预测运动目标的位置。这种算法的早期应用之一是导弹制导。
- Meanshift和Camshift:这是定位密度函数最大值的算法,它们还用于跟踪。
单目标跟踪器(Single object trackers):在这类跟踪器中,第一个帧使用矩形标记,以指示要跟踪的对象的位置。然后使用跟踪算法在后续帧中跟踪对象。在大多数实际应用程序中,这些跟踪器与对象检测器一起使用。 - 多目标跟踪查找算法(Multiple object track finding algorithms):当我们有一个快速的目标检测器时,在每一帧中检测多个对象,然后运行一个跟踪查找算法来识别一个帧中的哪个矩形与下一个帧中的矩形相对应是有意义的。
这些算法各有优缺点,可以根据实际应用场景选择适合的算法。
具体调用步骤如下:
-
打开视频帧第一帧
-
框选目标,每选择一个目标按Enter键确认选择
-
按Esc退出框选模式
-
程序执行跟踪算法并绘制预测框
#include <opencv2/opencv.hpp>
#include <opencv2/tracking.hpp>
#include "timestamp.hpp"using namespace cv;
using namespace std;//加载静态库
#if defined(_WIN32)&&defined(_DEBUG)
#pragma comment(lib, "opencv_world346d.lib")
#elif defined(_WIN32)
#pragma comment(lib, "opencv_world346.lib")
#endif// 支持的跟踪算法
vector<string> trackerTypes = { "BOOSTING", "MIL", "KCF", "TLD", "MEDIANFLOW", "GOTURN", "MOSSE", "CSRT" };// 根据名字创建跟踪器
Ptr<Tracker> createTrackerByName(string trackerType)
{
Ptr<Tracker> tracker;
if (trackerType == trackerTypes[0])
tracker = TrackerBoosting::create();
else if (trackerType == trackerTypes[1])
tracker = TrackerMIL::create();
else if (trackerType == trackerTypes[2])
tracker = TrackerKCF::create();
else if (trackerType == trackerTypes[3])
tracker = TrackerTLD::create();
else if (trackerType == trackerTypes[4])
tracker = TrackerMedianFlow::create();
else if (trackerType == trackerTypes[5])
tracker = TrackerGOTURN::create();
else if (trackerType == trackerTypes[6])
tracker = TrackerMOSSE::create();
else if (trackerType == trackerTypes[7])
tracker = TrackerCSRT::create();
else {
cout << "Incorrect tracker name" << endl;
cout << "Available trackers are: " << endl;
for (vector<string>::iterator it = trackerTypes.begin(); it != trackerTypes.end(); ++it)
std::cout << " " << *it << endl;
}
return tracker;
}// Fill the vector with random colors
void getRandomColors(vector<Scalar> &colors, int numColors)
{
RNG rng(0);
for (int i = 0; i < numColors; i++)
colors.push_back(Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)));
}int help(char* argv[])
{
std::cout << "please input arguments:" << argv[0] << "tracktype video.mp4 videoiotype"<< std::endl;return -1;
}
int main(int argc, char * argv[])
{
if(argc < 4){
return help(argv);
}cout << "默认算法是CSRT" << endl; cout << "支持的算法包括:" << endl; for (vector<string>::iterator it = trackerTypes.begin(); it != trackerTypes.end(); ++it) std::cout << " " << *it << endl; // 设置跟踪器类型。更改此设置以尝试不同的跟踪器。 字符串 trackerType; if(atoi(argv[1]) == 0) trackerType = "MOSSE"; else if(atoi(argv[1]) == 1) trackerType = "KCF"; else trackerType = "CSRT"; // 设置跟踪算法和视频的默认值 string videoPath = argv[2]; // 使用跟踪算法初始化 MultiTracker vector<Rect> bboxes; // 创建视频捕获对象以读取视频 cv::VideoCapture cap; if(atoi(argv[3]) == 0) cap.open(0); else{ cap.open(videoPath); } Mat frame; // 如果取消读取视频文件,则退出 if (!cap.isOpened()) { cout << "Error opening video file " << videoPath << endl; return -1; } // read first frame cap >> frame; // 在对象上绘制边界框 // selectROI 的默认行为是从中心开始绘制框 // 当 fromCenter 设置为 false 时,可以从左上角开始绘制框 bool showCrosshair = true; bool fromCenter = false; cout << "\n==========================================================\n"; cout << "OpenCV 表示按 c 取消对象选择过程" << endl; cout << "这是行不通的。按 Esc 键退出选择过程" << endl; cout << "\n==========================================================\n"; cv::selectROIs("MultiTracker", frame, bboxes, showCrosshair, fromCenter); // quit if there are no objects to track if (bboxes.size() < 1) return 0; vector<Scalar> colors; getRandomColors(colors, bboxes.size()); // 创建多跟踪器 Ptr<MultiTracker> multiTracker = cv::MultiTracker::create(); // 初始化 Multitracker for (int i = 0; i < bboxes.size(); i++) multiTracker->add(createTrackerByName(trackerType), frame, Rect2d(bboxes[i])); // 处理视频和跟踪对象 cout << "\n==========================================================\n"; cout << "开始跟踪,按 ESC 键退出。" << endl; while (cap.isOpened()) { // 从视频中获取帧 cap >> frame; // 如果到达视频末尾,请停止程序 if (frame.empty()) break; { timestamp ti("update"); // 使用新帧更新跟踪结果 multiTracker->update(frame); } // 绘制跟踪对象 for (unsigned i = 0; i < multiTracker->getObjects().size(); i++) { rectangle(frame, multiTracker->getObjects()[i], colors[i], 2, 1); } // 显示帧 imshow("MultiTracker1", frame); // 退出 X 按钮 if (waitKey(1) == 27) break; }
}