对于刚入门的OpenCV玩家,提起目标跟踪,马上想起的就是camshift,但是camshift跟踪往往达不到我们的跟踪要求,包括稳定性和准确性。
opencv3.1版本发行后,集成了多个跟踪算法,即tracker,大部分都是近年VOT竞赛榜上有名的算法,虽然仍有缺陷存在,但效果还不错。
ps:我在知乎上看到一个目标跟踪的介绍,感觉不错,链接在此!
单目标跟踪很简单,放一个官方例程供参考(opencv官方):
-
- #include
- #include
- #include
- #include
- #include
- #include
- using namespace std;
- using namespace cv;
- int main( int argc, char** argv ){
-
- if(argc<2){
- cout<<
- " Usage: tracker \n"
- " examples:\n"
- " example_tracking_kcf Bolt/img/%04d.jpg\n"
- " example_tracking_kcf faceocc2.webm\n"
- << endl;
- return 0;
- }
-
- Rect2d roi;
- Mat frame;
-
- Ptr tracker = TrackerKCF::create();
-
- std::string video = argv[1];
- VideoCapture cap(video);
-
- cap >> frame;
- roi=selectROI("tracker",frame);
-
- if(roi.width==0 || roi.height==0)
- return 0;
-
- tracker->init(frame,roi);
-
- printf("Start the tracking process, press ESC to quit.\n");
- for ( ;; ){
-
- cap >> frame;
-
- if(frame.rows==0 || frame.cols==0)
- break;
-
- tracker->update(frame,roi);
-
- rectangle( frame, roi, Scalar( 255, 0, 0 ), 2, 1 );
-
- imshow("tracker",frame);
-
- if(waitKey(1)==27)break;
- }
- return 0;
- }
-
其中, 跟踪器的创建可选以下几种,代表使用的跟踪算法;
- MIL
- BOOSTING
- MEDIANFLOW
- TLD
- KCF
eg-- Ptr tracker = Tracker::create("KCF");
多目标跟踪使用的是MultiTracker,如MultiTracker myTracker("KCF"),注意两点,添加目标用其成员函数myTracker.add(Mat src, Rect2d roi),获得跟踪结果使用myTracker.update(Mat src, vector targets),跟踪结果的序号即vector的序号。
以下代码为跟踪鼠标框选的目标,跟踪的目标个数大概为10个(原则上是没有上限的,但我电脑比较烂,目标多了会卡)
- #include
- #include "opencv2/opencv.hpp"
- #include
-
-
- using namespace cv;
- using namespace std;
-
- bool selectObject = false;
- Point origin;
- Rect selection;
- int trackObject = 0;
-
-
-
-
-
-
- void displayTrajectory(Mat img, vector traj, Scalar s)
- {
- if (!traj.empty())
- {
- for (size_t i = 0; i < traj.size() - 1; i++)
- {
- line(img, traj[i], traj[i + 1], s, 2, 8, 0);
- }
- }
- }
-
-
-
-
-
- void onMouse(int event, int x, int y, int, void*)
- {
- if (selectObject)
- {
- selection.x = MIN(x, origin.x);
- selection.y = MIN(y, origin.y);
- selection.width = std::abs(x - origin.x);
- selection.height = std::abs(y - origin.y);
-
- selection &= Rect(0, 0, src.cols, src.rows);
-
-
- }
- switch (event)
- {
- case CV_EVENT_LBUTTONDOWN:
- origin = Point(x, y);
- selection = Rect(x, y, 0, 0);
- selectObject = true;
- break;
- case CV_EVENT_LBUTTONUP:
- selectObject = false;
- if (selection.width > 0 && selection.height > 0)
- trackObject = -1;
- break;
- }
- }
-
- int main(int argc, char *argv[])
- {
- namedWindow("tracker");
- setMouseCallback("tracker", onMouse(), 0);
-
- MultiTracker myTracker("KCF");
- vector> trajectorys;
- int objectCounter = 0;
-
- VideoCapture cap(0);
- if (!cap.isOpened())
- {
- return -1;
- }
- Mat src;
- bool stop = false;
- while (!stop)
- {
- cap>>src;
-
- if (selectObject)
- {
- rectangle(src, selection, Scalar(0, 0, 255), 2, 8, 0);
- }
- if (trackObject < 0)
- {
- myTracker.add(src, selection);
-
- Point cen = Point(selection.x + selection.width / 2.0, selection.y + selection.height / 2.0);
- trajectorys.resize(objectCounter + 1);
- trajectorys[objectCounter].push_back(cen);
-
- objectCounter++;
- trackObject = 1;
-
- }
- if (trackObject)
- {
- vector r;
- myTracker.update(src, r);
-
- size_t s = r.size();
- RNG rng;
-
- for (size_t i = 0; i < s; i++)
- {
- Scalar scalar = Scalar(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
- rectangle(src, r[i], scalar, 2, 8, 0);
- Point C = Point(r[i].x + r[i].width / 2.0, r[i].y + r[i].height / 2.0);
- trajectorys[i].push_back(C);
- displayTrajectory(src, trajectorys[i], scalar);
- char name[10];
- sprintf_s(name, "%d", (i + 1));
- putText(src, name, r[i].tl(), 3, 0.8, Scalar(0, 255, 255), 2, 8, false);
- }
-
- }
- imshow("tracker", src);
- if (waitKey(30) == 27)
- {
- stop = true;
- }
- }
- return 0;
- }
-