zoukankan      html  css  js  c++  java
  • 最简单的目标跟踪(模版匹配)

    一、概述

           目标跟踪是计算机视觉领域的一个重要分支。研究的人很多,近几年也出现了很多很多的算法。大家看看淋漓满目的paper就知道了。但在这里,我们也聚焦下比较简单的算法,看看它的优势在哪里。毕竟有时候简单就是一种美。

           在这里我们一起来欣赏下“模板匹配”这个简单点的跟踪算法。它的思想很简单,我们把要跟踪的目标保存好,然后在每一帧来临的时候,我们在整个图像中寻找与这个目标最相似的,我们就相信这个就是目标了。那如何判断相似呢?就用到了一些相关性的东西了,这个在我之前的一篇博文里面介绍过,大家可以参考下:

           模板匹配中差值的平方和(SSD)与互相关准则的关系

    http://blog.csdn.net/zouxy09/article/details/8549743

           然后为了适应目标的变化,我们就需要随时更新我们要跟踪的目标。换句话来说,在跟踪t帧的时候,也就是在第t帧寻找目标的时候,是与t-1帧中我们找到的目标来进行比较的。这样目标的外观变化就会及时的更新。这个就叫做在线跟踪方法。当然了,这个策略会导致跟踪漂移的问题,这就是近几年很多跟踪算法关注的重要问题之一了。

    二、代码实现

           我的代码是基于VS2010+ OpenCV2.4.2的。代码可以读入视频,也可以读摄像头,两者的选择只需要在代码中稍微修改即可。对于视频来说,运行会先显示第一帧,然后我们用鼠标框选要跟踪的目标,然后跟踪器开始跟踪每一帧。对摄像头来说,就会一直采集图像,然后我们用鼠标框选要跟踪的目标,接着跟踪器开始跟踪后面的每一帧。具体代码如下:

    simpleTracker.cpp

    1. // Object tracking algorithm using matchTemplate  
    2. // Author : zouxy  
    3. // Date   : 2013-10-28  
    4. // HomePage : http://blog.csdn.net/zouxy09  
    5. // Email  : zouxy09@qq.com  
    6.   
    7. #include <opencv2/opencv.hpp>  
    8.   
    9. using namespace cv;  
    10. using namespace std;  
    11.   
    12. // Global variables  
    13. Rect box;  
    14. bool drawing_box = false;  
    15. bool gotBB = false;  
    16.   
    17. // bounding box mouse callback  
    18. void mouseHandler(int event, int x, int y, int flags, void *param){  
    19.   switch( event ){  
    20.   case CV_EVENT_MOUSEMOVE:  
    21.     if (drawing_box){  
    22.         box.width = x-box.x;  
    23.         box.height = y-box.y;  
    24.     }  
    25.     break;  
    26.   case CV_EVENT_LBUTTONDOWN:  
    27.     drawing_box = true;  
    28.     box = Rect( x, y, 0, 0 );  
    29.     break;  
    30.   case CV_EVENT_LBUTTONUP:  
    31.     drawing_box = false;  
    32.     if( box.width < 0 ){  
    33.         box.x += box.width;  
    34.         box.width *= -1;  
    35.     }  
    36.     if( box.height < 0 ){  
    37.         box.y += box.height;  
    38.         box.height *= -1;  
    39.     }  
    40.     gotBB = true;  
    41.     break;  
    42.   }  
    43. }  
    44.   
    45.   
    46. // tracker: get search patches around the last tracking box,  
    47. // and find the most similar one  
    48. void tracking(Mat frame, Mat &model, Rect &trackBox)  
    49. {  
    50.     Mat gray;  
    51.     cvtColor(frame, gray, CV_RGB2GRAY);  
    52.   
    53.     Rect searchWindow;  
    54.     searchWindow.width = trackBox.width * 3;  
    55.     searchWindow.height = trackBox.height * 3;  
    56.     searchWindow.x = trackBox.x + trackBox.width * 0.5 - searchWindow.width * 0.5;  
    57.     searchWindow.y = trackBox.y + trackBox.height * 0.5 - searchWindow.height * 0.5;  
    58.     searchWindow &= Rect(0, 0, frame.cols, frame.rows);  
    59.   
    60.     Mat similarity;  
    61.     matchTemplate(gray(searchWindow), model, similarity, CV_TM_CCOEFF_NORMED);   
    62.   
    63.     double mag_r;  
    64.     Point point;  
    65.     minMaxLoc(similarity, 0, &mag_r, 0, &point);  
    66.     trackBox.x = point.x + searchWindow.x;  
    67.     trackBox.y = point.y + searchWindow.y;  
    68.     model = gray(trackBox);  
    69. }  
    70.   
    71. int main(int argc, char * argv[])  
    72. {  
    73.     VideoCapture capture;  
    74.     capture.open("david.mpg");  
    75.     bool fromfile = true;  
    76.     //Init camera  
    77.     if (!capture.isOpened())  
    78.     {  
    79.         cout << "capture device failed to open!" << endl;  
    80.         return -1;  
    81.     }  
    82.     //Register mouse callback to draw the bounding box  
    83.     cvNamedWindow("Tracker", CV_WINDOW_AUTOSIZE);  
    84.     cvSetMouseCallback("Tracker", mouseHandler, NULL );   
    85.   
    86.     Mat frame, model;  
    87.     capture >> frame;  
    88.     while(!gotBB)  
    89.     {  
    90.         if (!fromfile)  
    91.             capture >> frame;  
    92.   
    93.         imshow("Tracker", frame);  
    94.         if (cvWaitKey(20) == 'q')  
    95.             return 1;  
    96.     }  
    97.     //Remove callback  
    98.     cvSetMouseCallback("Tracker", NULL, NULL );   
    99.       
    100.     Mat gray;  
    101.     cvtColor(frame, gray, CV_RGB2GRAY);   
    102.     model = gray(box);  
    103.   
    104.     int frameCount = 0;  
    105.   
    106.     while (1)  
    107.     {  
    108.         capture >> frame;  
    109.         if (frame.empty())  
    110.             return -1;  
    111.         double t = (double)cvGetTickCount();  
    112.         frameCount++;  
    113.   
    114.         // tracking  
    115.         tracking(frame, model, box);      
    116.   
    117.         // show  
    118.         stringstream buf;  
    119.         buf << frameCount;  
    120.         string num = buf.str();  
    121.         putText(frame, num, Point(20, 20), FONT_HERSHEY_SIMPLEX, 1, Scalar(0, 0, 255), 3);  
    122.         rectangle(frame, box, Scalar(0, 0, 255), 3);  
    123.         imshow("Tracker", frame);  
    124.   
    125.   
    126.         t = (double)cvGetTickCount() - t;  
    127.         cout << "cost time: " << t / ((double)cvGetTickFrequency()*1000.) << endl;  
    128.   
    129.         if ( cvWaitKey(1) == 27 )  
    130.             break;  
    131.     }  
    132.   
    133.     return 0;  
    134. }  

    三、结果

           我们对在目标跟踪领域一个benchmark的视频-david来测试下代码的效果。如下图所以,每帧的帧号在右上角所示。这个视频的光照变化是挺大的,但是简单的模板匹配方法还是可以挺有效的进行跟踪的,而且速度很快,在这个视频中,只花费了1ms左右(耗时的长度与目标框的大小和机器的性能有关)。

  • 相关阅读:
    Java实现 LeetCode 697 数组的度(类似于数组的map)
    Java实现 LeetCode 697 数组的度(类似于数组的map)
    Java实现 LeetCode 697 数组的度(类似于数组的map)
    Java实现 LeetCode 696 计数二进制子串(暴力)
    Java实现 LeetCode 696 计数二进制子串(暴力)
    Java实现 LeetCode 696 计数二进制子串(暴力)
    Java实现 LeetCode 695 岛屿的最大面积(DFS)
    Java实现 LeetCode 695 岛屿的最大面积(DFS)
    PHP serialize() 函数
    PHP print_r() 函数
  • 原文地址:https://www.cnblogs.com/ywsoftware/p/4434306.html
Copyright © 2011-2022 走看看