opencv3之目标跟踪(单目标、多目标)

来源:互联网 发布:led灯 知乎 编辑:程序博客网 时间:2024/06/01 10:36

对于刚入门的OpenCV玩家,提起目标跟踪,马上想起的就是camshift,但是camshift跟踪往往达不到我们的跟踪要求,包括稳定性和准确性。

opencv3.1版本发行后,集成了多个跟踪算法,即tracker,大部分都是近年VOT竞赛榜上有名的算法,虽然仍有缺陷存在,但效果还不错。

ps:我在知乎上看到一个目标跟踪的介绍,感觉不错,链接在此!

单目标跟踪很简单,放一个官方例程供参考(opencv官方):

[c++] view plain copy
  1.    
  2. #include <opencv2 core="" utility="" hpp="">  
  3. #include <opencv2 tracking="" hpp="">  
  4. #include <opencv2 videoio="" hpp="">  
  5. #include <opencv2 highgui="" hpp="">  
  6. #include <iostream>  
  7. #include <cstring>  
  8. using namespace std;  
  9. using namespace cv;  
  10. int main( int argc, char** argv ){  
  11.   // show help  
  12.   if(argc<2){  
  13.     cout<<  
  14.       " Usage: tracker <video_name>\n"  
  15.       " examples:\n"  
  16.       " example_tracking_kcf Bolt/img/%04d.jpg\n"  
  17.       " example_tracking_kcf faceocc2.webm\n"  
  18.       << endl;  
  19.     return 0;  
  20.   }  
  21.   // declares all required variables  
  22.   Rect2d roi;  
  23.   Mat frame;  
  24.   // create a tracker object  
  25.   Ptr<tracker> tracker = TrackerKCF::create();  
  26.   // set input video  
  27.   std::string video = argv[1];  
  28.   VideoCapture cap(video);  
  29.   // get bounding box  
  30.   cap >> frame;  
  31.   roi=selectROI("tracker",frame);  
  32.   //quit if ROI was not selected  
  33.   if(roi.width==0 || roi.height==0)  
  34.     return 0;  
  35.   // initialize the tracker  
  36.   tracker->init(frame,roi);  
  37.   // perform the tracking process  
  38.   printf("Start the tracking process, press ESC to quit.\n");  
  39.   for ( ;; ){  
  40.     // get frame from the video  
  41.     cap >> frame;  
  42.     // stop the program if no more images  
  43.     if(frame.rows==0 || frame.cols==0)  
  44.       break;  
  45.     // update the tracking result  
  46.     tracker->update(frame,roi);  
  47.     // draw the tracked object  
  48.     rectangle( frame, roi, Scalar( 255, 0, 0 ), 2, 1 );  
  49.     // show image with the tracked object  
  50.     imshow("tracker",frame);  
  51.     //quit on ESC button  
  52.     if(waitKey(1)==27)break;  
  53.   }  
  54.   return 0;  
  55. }  
  56. </tracker></video_name></cstring></iostream></opencv2></opencv2></opencv2></opencv2>  

其中, 跟踪器的创建可选以下几种,代表使用的跟踪算法;

  • MIL
  • BOOSTING
  • MEDIANFLOW
  • TLD
  • KCF

eg-- Ptr<Tracker> tracker = Tracker::create("KCF"); 

多目标跟踪使用的是MultiTracker,如MultiTracker myTracker("KCF"),注意两点,添加目标用其成员函数myTracker.add(Mat src, Rect2d roi),获得跟踪结果使用myTracker.update(Mat src, vector<Rect2d> targets),跟踪结果的序号即vector的序号。

以下代码为跟踪鼠标框选的目标,跟踪的目标个数大概为10个(原则上是没有上限的,但我电脑比较烂,目标多了会卡)

[c++] view plain copy
  1. #include <stdafx h="">  
  2. #include "opencv2/opencv.hpp"  
  3. #include <vector>  
  4.   
  5.   
  6. using namespace cv;  
  7. using namespace std;  
  8.   
  9. bool selectObject = false;  
  10. Point origin;//用于保存鼠标选择第一次单击时点的位置    
  11. Rect selection;//用于保存鼠标选择的矩形框    
  12. int trackObject = 0;  
  13.   
  14. /*------------------------------- 
  15.  
  16. 函数功能 显示轨迹 
  17.  
  18. --------------------------------*/  
  19. void displayTrajectory(Mat img, vector<point> traj, Scalar s)  
  20. {  
  21.     if (!traj.empty())  
  22.     {  
  23.         for (size_t i = 0; i < traj.size() - 1; i++)  
  24.         {  
  25.             line(img, traj[i], traj[i + 1], s, 2, 8, 0);  
  26.         }  
  27.     }  
  28. }  
  29. /*------------------------------- 
  30.  
  31. 鼠标控制 
  32.  
  33. --------------------------------*/  
  34. void onMouse(int event, int x, int y, intvoid*)  
  35. {  
  36.     if (selectObject)//只有当鼠标左键按下去时才有效,然后通过if里面代码就可以确定所选择的矩形区域selection了    
  37.     {  
  38.         selection.x = MIN(x, origin.x);//矩形左上角顶点坐标    
  39.         selection.y = MIN(y, origin.y);  
  40.         selection.width = std::abs(x - origin.x);//矩形宽    
  41.         selection.height = std::abs(y - origin.y);//矩形高    
  42.   
  43.         selection &= Rect(0, 0, src.cols, src.rows);//用于确保所选的矩形区域在图片范围内  
  44.         //rectangle(src,selection,Scalar(0,0,255),2);  
  45.   
  46.     }  
  47.     switch (event)  
  48.     {  
  49.     case CV_EVENT_LBUTTONDOWN:  
  50.         origin = Point(x, y);  
  51.         selection = Rect(x, y, 0, 0);//鼠标刚按下去时初始化了一个矩形区域    
  52.         selectObject = true;  
  53.         break;  
  54.     case CV_EVENT_LBUTTONUP:  
  55.         selectObject = false;  
  56.         if (selection.width > 0 && selection.height > 0)  
  57.             trackObject = -1;  
  58.         break;  
  59.     }  
  60. }  
  61.   
  62. int main(int argc, char *argv[])  
  63. {  
  64.     namedWindow("tracker");  
  65.     setMouseCallback("tracker", onMouse(), 0);  
  66.       
  67.     MultiTracker myTracker("KCF");  
  68.     vector<vector<point>> trajectorys;//轨迹记录  
  69.     int objectCounter = 0;  
  70.   
  71.     VideoCapture cap(0);//打开默认的摄像头    
  72.     if (!cap.isOpened())  
  73.     {  
  74.         return -1;  
  75.     }  
  76.     Mat src;  
  77.     bool stop = false;  
  78.     while (!stop)  
  79.     {  
  80.         cap>>src;   
  81.   
  82.         if (selectObject)  
  83.         {  
  84.             rectangle(src, selection, Scalar(0, 0, 255), 2, 8, 0);  
  85.         }  
  86.         if (trackObject < 0)  
  87.         {  
  88.             myTracker.add(src, selection);  
  89.   
  90.             Point cen = Point(selection.x + selection.width / 2.0, selection.y + selection.height / 2.0);  
  91.             trajectorys.resize(objectCounter + 1);  
  92.             trajectorys[objectCounter].push_back(cen);//从[0]开始初始化轨迹起始点  
  93.   
  94.             objectCounter++;//待跟踪目标个数加1  
  95.             trackObject = 1;  
  96.   
  97.         }  
  98.         if (trackObject)  
  99.         {  
  100.             vector<rect2d> r;  
  101.             myTracker.update(src, r);  
  102.   
  103.             size_t s = r.size();  
  104.             RNG rng;  
  105.   
  106.             for (size_t i = 0; i < s; i++)  
  107.             {  
  108.                 Scalar scalar = Scalar(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));  
  109.                 rectangle(src, r[i], scalar, 2, 8, 0);  
  110.                 Point C = Point(r[i].x + r[i].width / 2.0, r[i].y + r[i].height / 2.0);  
  111.                 trajectorys[i].push_back(C);  
  112.                 displayTrajectory(src, trajectorys[i], scalar);  
  113.                 char name[10];  
  114.                 sprintf_s(name, "%d", (i + 1));  
  115.                 putText(src, name, r[i].tl(), 3, 0.8, Scalar(0, 255, 255), 2, 8, false);  
  116.             }  
  117.   
  118.         }  
  119.         imshow("tracker", src);  
  120.         if (waitKey(30) == 27) //Esc键退出    
  121.         {  
  122.             stop = true;  
  123.         }  
  124.     }  
  125.     return 0;  
  126. }  
  127. </rect2d></point></point></vector></stdafx>