KCF跟踪算法代码整理

来源:互联网 发布:网页游戏的源码 编辑:程序博客网 时间:2024/05/22 00:26

KCF: Kernelized correlation filter

KCF是一种鉴别式追踪方法,这类方法一般都是在追踪过程中训练一个目标检测器,使用目标检测器去检测下一帧预测位置是否是目标,然后再使用新检测结果去更新训练集进而更新目标检测器。而在训练目标检测器时一般选取目标区域为正样本,目标的周围区域为负样本,当然越靠近目标的区域为正样本的可能性越大。


论文:High-Speed Tracking with Kernelized Correlation Filters

算法源码:opencv_contribe/modules//tracking/tackerkcf.cpp

调用:参考../opencv_contrib/modules/tracking/samples/kcf.cpp

备注: opencv3.1.0与opencv_contrib配置参考http://blog.csdn.net/jay463261929/article/details/53197228;


        我原本也打算写一篇关于KCF算法原理的认知的,最后还是打算放弃,因为我学习参考的博主都写的很不错,所以还是打算把代码贴出。。。。


算法调用

      调用很简单就2个函数,但是在调用之前你需要opencv3.1.0与opencv_contrib配置好第一个函数初始化init(Mat frame, Rect2d roi),  //frame 为输入的彩色图,roi是要跟踪的目标区域,大小为刚好将目标框住就OK, Rect2就是Rect(x,y,w,h);

       第二个函数的目的是训练检测,因为该算法的原因就是先训练再检测,再训练再检测,这样不断循环:update(Mat frame, Rect2d result); //frame 为输入的彩色图, result是跟踪到目标的区域,大小跟初始化时roi的大小相等。 

    主要的头文件:

     #include <opencv2/core/utility.hpp> 
     #include <opencv2/tracking.hpp>


     例子:

    // 创建一个跟踪对象
    Ptr<Tracker> tracker = Tracker::create( "KCF" );

    // 设置输入的视频
     VideoCapture cap(“ETH-Linthescher.mp4”);

     Mat frame;
     cap >> frame;
 
     //quit if ROI was not selected
     if(roi.width==0 || roi.height==0)
         return 0;

      // 初始化
      tracker->init(frame,roi);

       //开始跟踪
       printf("Start the tracking process, press ESC to quit.\n");
      for ( ;; )

     {
         // get frame from the video
         cap >> frame;

         // stop the program if no more images
         if(frame.rows==0 || frame.cols==0)
          break;

         // 更新跟踪结果
          tracker->update(frame,roi);

          // draw the tracked object
          rectangle( frame, roi, Scalar( 255, 0, 0 ), 2, 1 );

         // show image with the tracked object
         imshow("tracker",frame);

         //quit on ESC button
         if(waitKey(1)==27)break;
  }

    学习完KCF算法的调用,是不是感觉该算法其实很简单,就2个函数而已,那你就错了,那是因为主角还没登场。。。大家以热烈的掌声有请我们的主角闪亮登场吧!

      初始化:

       这是算法中初始化函数的定义:bool TrackerKCFImpl::initImpl(const Mat& /*image*/, const Rect2d& boundingBox ),细心的朋友会发现其实初始化跟输入的图像没关系。

      初始化完成了4个任务:

      1)目标区域填充;

      2)创建汉宁窗;

      3)生成一个高斯响应;

      4)对高斯响应求傅里叶变换。


      1)目标区域填充

       目的是将输入的目标区域扩大2倍,因为后面的所有工作就是在扩大后的区域内进行的。

       //params.resize = true (true表示图像可以缩放),  max_patch_size=80*80; 

      if(params.resize && roi.width*roi.height>params.max_patch_size)
      {
           resizeImage=true; //
如果为true,表示后面都是缩小一倍的图像进行处理,所有的框也跟着缩小一倍         

           roi.x/=2.0;
           roi.y/=2.0;
           roi.width/=2.0;
           roi.height/=2.0;
     }

    roi.x-=roi.width/2;
    roi.y-=roi.height/2;
    roi.width*=2;
    roi.height*=2;    

     由于跟踪的区域是固定的,所有摄像机要与目标保持固定的距离。


      2))创建汉宁窗

         目的是采样时为不同的样本分配不同的权重,kcf算法实际是采样了一个样本作为base样本,别的样本都是通过对base样本的平移得到,虚拟出来的样本。一般对样本都采用非正即负的方法来标记训练样本,即正样本标签为1,负样本为0。这样标记样本的方法不能很好的反应每个负样本的权重,即对离中心目标远的样本和离中心目标近的样本等同看待。但是在实际中我们需要对不同的负样本不同的看待,就有了根据样本中心离目标的远近分别赋值 [0,1]范数的数。离目标越近,值越趋向于1,离目标越远,值越趋向于0. kcf就是根据汉宁窗来对不同样本分配不同的权重。

  

       hann(i,j) = 0.25 * [1 - cos( (2*pi*i) / (w-1))] * [1 - cos( (2*pi*j) / (h-1))]; 

       //(i,j) 是位置,(w,h)是创建汉宁窗的大小,0.25是为了归一化到[0,1],  hann(i,j)的值就是每样样本的权重。

      函数是: createHanningWindow(hann, roi.size(), CV_64F);

      

       3)生成一个高斯响应

       //计算高斯函数的均方差
       output_sigma=sqrt(roi.width*roi.height)*params.output_sigma_factor;  //params.output_sigma_factor=1.0/16.0
       output_sigma=-0.5/(output_sigma*output_sigma);   //a=-1/(2*a^2)


      
y(i,j) = exp(output_sigma × [ (i-w/2+1)^2 + (j-h/2+1)^2])

      //(i,j) 是位置,(w,h)是窗口大小,y(i,j)的值就是每个样本的实际响应值。

      4)高斯响应的傅里叶变换

        fft2(y,yf);  //yf 是高斯响应的傅里叶变换


      训练:

     1)特征提取:在这个函数getSubWindow()完成,提取特征为彩色+灰度;彩色特征存放在这features_npca,灰度特征存放在features_pca。

     提取灰度特征:

       Mat  feat = frame(roi); //w*h*1

       feat=feat/255.0-0.5; // normalize to range -0.5 .. 0.5
       feat=feat.mul(hann); // hann window filter

      X[1] = feat; //w*h*1

     提取彩色特征:

     Mat patch= frame(roi); //w*h*3 

       extractCN(patch, feat); // feat  w*h*10, 该算法是将颜色划分的更细,内容在featureColorName.cpp
      feat=feat.mul(hann_cn); // hann window filter

     X[0] = feat; //w*h*10

     2)  将彩色特征feat(w*h*10)进行pca主成分分析,其实就是压缩,默认的参数设置压缩大小compress_size=2,压缩后彩色特征X[0]就变成w*h*2


    检测:

  1. 先提取特征;

  2.  // extract the maximum response
      minMaxLoc( response, &minVal, &maxVal, &minLoc, &maxLoc ); //maxLoc的位置代表跟踪到目标的中心点
      roi.x+=(maxLoc.x-roi.width/2+1);
      roi.y+=(maxLoc.y-roi.height/2+1); //跟踪结果,目标大小是固定的 

   

备注:

1. KCF跟踪算法是不带识别的,也不需要特定哪一类物体;

2.测试opencv_contrib带的KCF跟踪算法(灰色+彩色特征)与github中作者给出的hog特征,前者效果比较好,但是论文中给出后者效果好。


参考:

http://www.cnblogs.com/YiXiaoZhou/p/5925019.html

http://blog.csdn.net/shenxiaolu1984/article/details/50905283

http://www.jianshu.com/p/9aacd075a689

http://www.360doc.com/content/16/0302/13/25664332_538789414.shtml

http://blog.csdn.net/daunxx/article/details/51578787?locationNum=11

     
0 0
原创粉丝点击