KCF目标跟踪代码及注释

本文详细介绍了KCF(Kernelized Correlation Filters)目标跟踪算法的实现,包括Tracker类的定义,KCFTracker类的成员函数,如构造函数、初始化和更新方法。代码展示了如何使用OpenCV库进行特征提取、高斯卷积核计算以及亚像素峰值检测等关键步骤,同时涵盖了多尺度和固定窗口等选项。
摘要由CSDN通过智能技术生成

tracker.h:定义Tracker类

[cpp]  view plain  copy
  1. #pragma once  
  2.   
  3. #include <opencv2/opencv.hpp>  
  4. #include <string>  
  5.   
  6. class Tracker  
  7. {  
  8. public:  
  9.     Tracker()  {}  
  10.    virtual  ~Tracker() { }  
  11.   
  12.     virtual void init(const cv::Rect &roi, cv::Mat image) = 0;  
  13.     virtual cv::Rect  update( cv::Mat image)=0;  
  14.   
  15.   
  16. protected:  
  17.     cv::Rect_<float> _roi;  
  18. };  


kcftracker.hpp:继承Tracker定义KCFTracker

[html]  view plain  copy
  1. #pragma once  
  2.   
  3. #include "tracker.h"  
  4.   
  5. #ifndef _OPENCV_KCFTRACKER_HPP_  
  6. #define _OPENCV_KCFTRACKER_HPP_  
  7. #endif  
  8.   
  9. class KCFTracker : public Tracker  
  10. {  
  11. public:  
  12.     // Constructor  
  13.     // 构造KCF跟踪器的类  
  14.     KCFTracker(bool hog = true,                 // 使用hog特征  
  15.                 bool fixed_window = true,       //使用固定窗口大小  
  16.                 bool multiscale = true,         //使用多尺度  
  17.                 bool lab = true);               //使用lab色空间特征  
  18.   
  19.     // Initialize tracker  
  20.     // 初始化跟踪器, roi 是目标初始框的引用, image 是进入跟踪的第一帧图像  
  21.     virtual void init(const cv::Rect &roi, cv::Mat image);  
  22.   
  23.     // Update position based on the new frame  
  24.     // 使用新一帧更新图像, image 是新一帧图像  
  25.     virtual cv::Rect update(cv::Mat image);  
  26.   
  27.     float interp_factor;        // linear interpolation factor for adaptation  
  28.                                 // 自适应的线性插值因子,会因为hog,lab的选择而变化  
  29.     float sigma;                // gaussian kernel bandwidth  
  30.                                 // 高斯卷积核带宽,会因为hog,lab的选择而变化  
  31.     float lambda;               // regularization  
  32.                                 // 正则化,0.0001  
  33.     int cell_size;              // HOG cell size  
  34.                                 // HOG元胞数组尺寸,4  
  35.     int cell_sizeQ;             // cell size^2, to avoid repeated operations  
  36.                                 // 元胞数组内像素数目,16,为了计算省事  
  37.     float padding;              // extra area surrounding the target  
  38.                                 // 目标扩展出来的区域,2.5  
  39.     float output_sigma_factor;  // bandwidth of gaussian target  
  40.                                 // 高斯目标的带宽,不同hog,lab会不同  
  41.     int template_size;          // template size  
  42.                                 // 模板大小,在计算_tmpl_sz时,  
  43.                                 // 较大变成被归一成96,而较小边长按比例缩小  
  44.     float scale_step;           // scale step for multi-scale estimation  
  45.                                 // 多尺度估计的时候的尺度步长  
  46.     float scale_weight;         // to downweight detection scores of other scales for added stability  
  47.                                 // 为了增加其他尺度检测时的稳定性,给检测结果峰值做一定衰减,为原来的0.95倍  
  48.   
  49. protected:  
  50.     // Detect object in the current frame.  
  51.     // 检测当前帧的目标  
  52.     //z是前一阵的训练/第一帧的初始化结果, x是当前帧当前尺度下的特征, peak_value是检测结果峰值  
  53.     cv::Point2f detect(cv::Mat z, cv::Mat x, float &peak_value);  
  54.   
  55.     // train tracker with a single image  
  56.     // 使用当前图像的检测结果进行训练  
  57.     // x是当前帧当前尺度下的特征, train_interp_factor是interp_factor  
  58.     void train(cv::Mat x, float train_interp_factor);  
  59.   
  60.     // Evaluates a Gaussian kernel with bandwidth SIGMA for all relative shifts between input images X and Y,  
  61.     // which must both be MxN. They must also be periodic (ie., pre-processed with a cosine window).  
  62.     // 使用带宽SIGMA计算高斯卷积核以用于所有图像X和Y之间的相对位移  
  63.     // 必须都是MxN大小。二者必须都是周期的(即,通过一个cos窗口进行预处理)  
  64.     cv::Mat gaussianCorrelation(cv::Mat x1, cv::Mat x2);  
  65.   
  66.     // Create Gaussian Peak. Function called only in the first frame.  
  67.     // 创建高斯峰函数,函数只在第一帧的时候执行  
  68.     cv::Mat createGaussianPeak(int sizey, int sizex);  
  69.   
  70.     // Obtain sub-window from image, with replication-padding and extract features  
  71.     // 从图像得到子窗口,通过赋值填充并检测特征  
  72.     cv::Mat getFeatures(const cv::Mat & image, bool inithann, float scale_adjust = 1.0f);  
  73.   
  74.     // Initialize Hanning window. Function called only in the first frame.  
  75.     // 初始化hanning窗口。函数只在第一帧被执行。  
  76.     void createHanningMats();  
  77.   
  78.     // Calculate sub-pixel peak for one dimension  
  79.     // 计算一维亚像素峰值  
  80.     float subPixelPeak(float left, float center, float right);  
  81.   
  82.     cv::Mat _alphaf;            // 初始化/训练结果alphaf,用于检测部分中结果的计算  
  83.     cv::Mat _prob;              // 初始化结果prob,不再更改,用于训练  
  84.     cv::Mat _tmpl;              // 初始化/训练的结果,用于detect的z  
  85.     cv::Mat _num;               // 貌似都被注释掉了  
  86.     cv::Mat _den;               // 貌似都被注释掉了  
  87.     cv::Mat _labCentroids;      // lab质心数组  
  88.   
  89. private:  
  90.     int size_patch[3];          // hog特征的sizeY,sizeX,numFeatures  
  91.     cv::Mat hann;               // createHanningMats()的计算结果  
  92.     cv::Size _tmpl_sz;          // hog元胞对应的数组大小  
  93.     float _scale;               // 修正成_tmpl_sz后的尺度大小  
  94.     int _gaussian_size;         // 未引用???  
  95.     bool _hogfeatures;          // hog标志位  
  96.     bool _labfeatures;          // lab标志位  
  97. };  

kcftracker.cpp:KCFTracker类中函数的定义

[cpp]  view plain  copy
  1. #ifndef _KCFTRACKER_HEADERS  
  2. #include "kcftracker.hpp"  
  3. #include "ffttools.hpp"  
  4. #include "recttools.hpp"  
  5. #include "fhog.hpp"  
  6. #include "labdata.hpp"  
  7. #endif  
  8.   
  9. // Constructor  
  10. // 初始化KCF类参数  
  11. KCFTracker::KCFTracker(bool hog, bool fixed_window, bool multiscale, bool lab)  
  12. {  
  13.   
  14.     // Parameters equal in all cases  
  15.     lambda = 0.0001;  
  16.     padding = 2.5;   
  17.     //output_sigma_factor = 0.1;  
  18.     output_sigma_factor = 0.125;  
  19.   
  20.   
  21.     if (hog) {    // HOG  
  22.         // VOT  
  23.         interp_factor = 0.012;   //插值因子
  24.         sigma = 0.6;   
  25.         // TPAMI  
  26.         //interp_factor = 0.02;  
  27.         //sigma = 0.5;   
  28.         cell_size = 4;  
  29.         _hogfeatures = true;  
  30.   
  31.         if (lab) {  
  32.             interp_factor = 0.005;  
  33.             sigma = 0.4;   
  34.             //output_sigma_factor = 0.025;  
  35.             output_sigma_factor = 0.1;  
  36.   
  37.             _labfeatures = true;  
  38.             _labCentroids = cv::Mat(nClusters, 3, CV_32FC1, &data);    //lab质心,,将其初始化为 nClusters(聚类)行,3列,类型为 CV_32FC1,数据全部初始化为data
  39.             cell_sizeQ = cell_size*cell_size;  
  40.         }  
  41.         else{  
  42.             _labfeatures = false;  
  43.         }  
  44.     }  
  45.     else {   // RAW  
  46.         interp_factor = 0.075;  
  47.         sigma = 0.2;   
  48.         cell_size = 1;  
  49.         _hogfeatures = false;  
  50.   
  51.         if (lab) {  
  52.             printf("Lab features are only used with HOG features.\n");  
  53.             _labfeatures = false;  
  54.         }  
  55.     }  
  56.   
  57.   
  58.     if (multiscale) { // multiscale  
  59.         template_size = 96;       //模板尺寸
  60.         //template_size = 100;  
  61.         scale_step = 1.20;//1.05;  
  62.         scale_weight = 0.95;  
  63.         if (!fixed_window) {  
  64.             //printf("Multiscale does not support non-fixed window.\n");  
  65.             fixed_window = true;  
  66.         }  
  67.     }  
  68.     else if (fixed_window) {  // fit correction without multiscale    //拟合校正
  69.         template_size = 96;  
  70.         //template_size = 100;  
  71.         scale_step = 1;  
  72.     }  
  73.     else {  
  74.         template_size = 1;  
  75.         scale_step = 1;  
  76.     }  
  77. }  
  78.   
  79. // Initialize tracker   
  80. // 使用第一帧和它的跟踪框,初始化KCF跟踪器  
  81. void KCFTracker::init(const cv::Rect &roi, cv::Mat image)  
  82. {  
  83.     _roi = roi;  
  84.     assert(roi.width >= 0 && roi.height >= 0);  
  85.     _tmpl = getFeatures(image, 1);                                                                              // 获取特征,在train里面每帧修改  
  86.     _prob = createGaussianPeak(size_patch[0], size_patch[1]);                           // 这个不修改了,只初始化一次  
  87.     _alphaf = cv::Mat(size_patch[0], size_patch[1], CV_32FC2, float(0));    // 获取特征,在train里面每帧修改  
  88.     //_num = cv::Mat(size_patch[0], size_patch[1], CV_32FC2, float(0));  
  89.     //_den = cv::Mat(size_patch[0], size_patch[1], CV_32FC2, float(0));  
  90.     train(_tmpl, 1.0); // train with initial frame  
  91.  }  
  92.    
  93. // Update position based on the new frame  
  94. // 基于当前帧更新目标位置  
  95. cv::Rect KCFTracker::update(cv::Mat image)  
  96. {  
  97.         // 修正边界  
  98.     if (_roi.x + _roi.width <= 0) _roi.x = -_roi.width + 1;  
  99.     if (_roi.y + _roi.height <= 0) _roi.y = -_roi.height + 1;  
  100.     if (_roi.x >= image.cols - 1) _roi.x = image.cols - 2;  
  101.     if (_roi.y >= image.rows - 1) _roi.y = image.rows - 2;  
  102.   
  103.         // 跟踪框中心  
  104.     float cx = _roi.x + _roi.width / 2.0f;  
  105.     float cy = _roi.y + _roi.height / 2.0f;  
  106.   
  107.         // 尺度不变时检测峰值结果  
  108.     float peak_value;  
  109.     cv::Point2f res = detect(_tmpl, getFeatures(image, 0, 1.0f), peak_value);  
  110.   
  111.         // 略大尺度和略小尺度进行检测  
  112.     if (scale_step != 1) {  
  113.         // Test at a smaller _scale  
  114.         // 使用一个小点的尺度测试  
  115.         float new_peak_value;  
  116.         cv::Point2f new_res = detect(_tmpl, getFeatures(image, 0, 1.0f / scale_step), new_peak_value);  
  117.   
  118.                 // 做减益还比同尺度大就认为是目标  
  119.         if (scale_weight * new_peak_value > peak_value) {  
  120.             res = new_res;  
  121.             peak_value = new_peak_value;  
  122.             _scale /= scale_step;  
  123.             _roi.width /= scale_step;  
  124.             _roi.height /= scale_step;  
  125.         }  
  126.   
  127.         // Test at a bigger _scale  
  128.         new_res = detect(_tmpl, getFeatures(image, 0, scale_step), new_peak_value);  
  129.   
  130.         if (scale_weight * new_peak_value > peak_value) {  
  131.             res = new_res;  
  132.             peak_value = new_peak_value;  
  133.             _scale *= scale_step;  
  134.             _roi.width *= scale_step;  
  135.             _roi.height *= scale_step;  
  136.         }  
  137.     }  
  138.   
  139.     // Adjust by cell size and _scale  
  140.     // 因为返回的只有中心坐标,使用尺度和中心坐标调整目标框  
  141.     _roi.x = cx - _roi.width / 2.0f + ((float) res.x * cell_size * _scale);  
  142.     _roi.y = cy - _roi.height / 2.0f + ((float) res.y * cell_size * _scale);  
  143.   
  144.     if (_roi.x >= image.cols - 1) _roi.x = image.cols - 1;  
  145.     if (_roi.y >= image.rows - 1) _roi.y = image.rows - 1;  
  146.     if (_roi.x + _roi.width <= 0) _roi.x = -_roi.width + 2;  
  147.     if (_roi.y + _roi.height <= 0) _roi.y = -_roi.height + 2;  
  148.   
  149.     assert(_roi.width >= 0 && _roi.height >= 0);  
  150.       
  151.     // 使用当前的检测框来训练样本参数  
  152.     cv::Mat x = getFeatures(image, 0);  
  153.     train(x, interp_factor);  
  154.   
  155.     return _roi;        //返回检测框  
  156. }  
  157.   
  158.   
  159. // Detect object in the current frame.  
  160. // z为前一帧样本  
  161. // x为当前帧图像  
  162. // peak_value为输出的峰值  
  163. cv::Point2f KCFTracker::detect(cv::Mat z, cv::Mat x, float &peak_value)  
  164. {  
  165.     using namespace FFTTools;  
  166.   
  167.         // 做变换得到计算结果res  
  168.     cv::Mat k = gaussianCorrelation(x, z);  
  169.     cv::Mat res = (real(fftd(complexMultiplication(_alphaf, fftd(k)), true)));  
  170.   
  171.     //minMaxLoc only accepts doubles for the peak, and integer points for the coordinates  
  172.     // 使用opencv的minMaxLoc来定位峰值坐标位置  
  173.     cv::Point2i pi;  
  174.     double pv;  
  175.     cv::minMaxLoc(res, NULL, &pv, NULL, &pi);  
  176.     peak_value = (float) pv;  
  177.   
  178.     //subpixel peak estimation, coordinates will be non-integer  
  179.     // 子像素峰值检测,坐标是非整形的  
  180.     cv::Point2f p((float)pi.x, (float)pi.y);  
  181.   
  182.     if (pi.x > 0 && pi.x < res.cols-1) {  
  183.         p.x += subPixelPeak(res.at<float>(pi.y, pi.x-1), peak_value, res.at<float>(pi.y, pi.x+1));  
  184.     }  
  185.   
  186.     if (pi.y > 0 && pi.y < res.rows-1) {  
  187.         p.y += subPixelPeak(res.at<float>(pi.y-1, pi.x), peak_value, res.at<float>(pi.y+1, pi.x));  
  188.     }  
  189.   
  190.     p.x -= (res.cols) / 2;  
  191.     p.y -= (res.rows) / 2;  
  192.   
  193.     return p;  
  194. }  
  195.   
  196. // train tracker with a single image  
  197. // 使用图像进行训练,得到当前帧的_tmpl,_alphaf  
  198. void KCFTracker::train(cv::Mat x, float train_interp_factor)  
  199. {  
  200.     using namespace FFTTools;  
  201.   
  202.     cv::Mat k = gaussianCorrelation(x, x);  
  203.     cv::Mat alphaf = complexDivision(_prob, (fftd(k) + lambda));  
  204.       
  205.     _tmpl = (1 - train_interp_factor) * _tmpl + (train_interp_factor) * x;  
  206.     _alphaf = (1 - train_interp_factor) * _alphaf + (train_interp_factor) * alphaf;  
  207.   
  208.   
  209.     /*cv::Mat kf = fftd(gaussianCorrelation(x, x)); 
  210.     cv::Mat num = complexMultiplication(kf, _prob); 
  211.     cv::Mat den = complexMultiplication(kf, kf + lambda); 
  212.      
  213.     _tmpl = (1 - train_interp_factor) * _tmpl + (train_interp_factor) * x; 
  214.     _num = (1 - train_interp_factor) * _num + (train_interp_factor) * num; 
  215.     _den = (1 - train_interp_factor) * _den + (train_interp_factor) * den; 
  216.  
  217.     _alphaf = complexDivision(_num, _den);*/  
  218.   
  219. }  
  220.   
  221. // Evaluates a Gaussian kernel with bandwidth SIGMA for all relative shifts between input images X and Y,  
  222. // which must both be MxN. They must    also be periodic (ie., pre-processed with a cosine window).  
  223. // 使用带宽SIGMA计算高斯卷积核以用于所有图像X和Y之间的相对位移  
  224. // 必须都是MxN大小。二者必须都是周期的(即,通过一个cos窗口进行预处理)  
  225. cv::Mat KCFTracker::gaussianCorrelation(cv::Mat x1, cv::Mat x2)  
  226. {  
  227.     using namespace FFTTools;  
  228.     cv::Mat c = cv::Mat( cv::Size(size_patch[1], size_patch[0]), CV_32F, cv::Scalar(0) );  
  229.     // HOG features  
  230.     if (_hogfeatures) {  
  231.         cv::Mat caux;  
  232.         cv::Mat x1aux;  
  233.         cv::Mat x2aux;  
  234.         for (int i = 0; i < size_patch[2]; i++) {  
  235.             x1aux = x1.row(i);   // Procedure do deal with cv::Mat multichannel bug  
  236.             x1aux = x1aux.reshape(1, size_patch[0]);  
  237.             x2aux = x2.row(i).reshape(1, size_patch[0]);  
  238.             cv::mulSpectrums(fftd(x1aux), fftd(x2aux), caux, 0, true);   
  239.             caux = fftd(caux, true);  
  240.             rearrange(caux);  
  241.             caux.convertTo(caux,CV_32F);  
  242.             c = c + real(caux);  
  243.         }  
  244.     }  
  245.     // Gray features  
  246.     else {  
  247.         cv::mulSpectrums(fftd(x1), fftd(x2), c, 0, true);  
  248.         c = fftd(c, true);  
  249.         rearrange(c);  
  250.         c = real(c);  
  251.     }  
  252.     cv::Mat d;   
  253.     cv::max(( (cv::sum(x1.mul(x1))[0] + cv::sum(x2.mul(x2))[0])- 2. * c) / (size_patch[0]*size_patch[1]*size_patch[2]) , 0, d);  
  254.   
  255.     cv::Mat k;  
  256.     cv::exp((-d / (sigma * sigma)), k);  
  257.     return k;  
  258. }  
  259.   
  260. // Create Gaussian Peak. Function called only in the first frame.  
  261. // 创建高斯峰函数,函数只在第一帧的时候执行  
  262. cv::Mat KCFTracker::createGaussianPeak(int sizey, int sizex)  
  263. {  
  264.     cv::Mat_<float> res(sizey, sizex);  
  265.   
  266.     int syh = (sizey) / 2;  
  267.     int sxh = (sizex) / 2;  
  268.   
  269.     float output_sigma = std::sqrt((float) sizex * sizey) / padding * output_sigma_factor;  
  270.     float mult = -0.5 / (output_sigma * output_sigma);  
  271.   
  272.     for (int i = 0; i < sizey; i++)  
  273.         for (int j = 0; j < sizex; j++)  
  274.         {  
  275.             int ih = i - syh;  
  276.             int jh = j - sxh;  
  277.             res(i, j) = std::exp(mult * (float) (ih * ih + jh * jh));  
  278.         }  
  279.     return FFTTools::fftd(res);  
  280. }  
  281.   
  282. // Obtain sub-window from image, with replication-padding and extract features  
  283. // 从图像得到子窗口,通过赋值填充并检测特征  
  284. cv::Mat KCFTracker::getFeatures(const cv::Mat & image, bool inithann, float scale_adjust)  
  285. {  
  286.     cv::Rect extracted_roi;  
  287.   
  288.     float cx = _roi.x + _roi.width / 2;  
  289.     float cy = _roi.y + _roi.height / 2;  
  290.   
  291.         // 初始化hanning窗, 其实只执行一次,只在第一帧的时候inithann=1  
  292.     if (inithann) {  
  293.         int padded_w = _roi.width * padding;  
  294.         int padded_h = _roi.height * padding;  
  295.           
  296.           
  297.         // 按照长宽比例修改长宽大小,保证比较大的边为template_size大小  
  298.         if (template_size > 1) {  // Fit largest dimension to the given template size  
  299.             if (padded_w >= padded_h)  //fit to width  
  300.                 _scale = padded_w / (float) template_size;  
  301.             else  
  302.                 _scale = padded_h / (float) template_size;  
  303.   
  304.             _tmpl_sz.width = padded_w / _scale;  
  305.             _tmpl_sz.height = padded_h / _scale;  
  306.         }  
  307.         else {  //No template size given, use ROI size  
  308.             _tmpl_sz.width = padded_w;  
  309.             _tmpl_sz.height = padded_h;  
  310.             _scale = 1;  
  311.             // original code from paper:  
  312.             /*if (sqrt(padded_w * padded_h) >= 100) {   //Normal size 
  313.                 _tmpl_sz.width = padded_w; 
  314.                 _tmpl_sz.height = padded_h; 
  315.                 _scale = 1; 
  316.             } 
  317.             else {   //ROI is too big, track at half size 
  318.                 _tmpl_sz.width = padded_w / 2; 
  319.                 _tmpl_sz.height = padded_h / 2; 
  320.                 _scale = 2; 
  321.             }*/  
  322.         }  
  323.   
  324.                 // 设置_tmpl_sz的长宽:向上取原来长宽的最小2*cell_size倍  
  325.                 // 其中,较大边长为104  
  326.         if (_hogfeatures) {  
  327.             // Round to cell size and also make it even  
  328.             _tmpl_sz.width = ( ( (int)(_tmpl_sz.width / (2 * cell_size)) ) * 2 * cell_size ) + cell_size*2;  
  329.             _tmpl_sz.height = ( ( (int)(_tmpl_sz.height / (2 * cell_size)) ) * 2 * cell_size ) + cell_size*2;  
  330.         }  
  331.         else {  //Make number of pixels even (helps with some logic involving half-dimensions)  
  332.             _tmpl_sz.width = (_tmpl_sz.width / 2) * 2;  
  333.             _tmpl_sz.height = (_tmpl_sz.height / 2) * 2;  
  334.         }  
  335.     }  
  336.   
  337.         // 检测区域大小  
  338.     extracted_roi.width = scale_adjust * _scale * _tmpl_sz.width;  
  339.     extracted_roi.height = scale_adjust * _scale * _tmpl_sz.height;  
  340.   
  341.     // center roi with new size  
  342.     // 检测区域坐上角坐标  
  343.     extracted_roi.x = cx - extracted_roi.width / 2;  
  344.     extracted_roi.y = cy - extracted_roi.height / 2;  
  345.   
  346.         // 提取目标区域像素,超边界则做填充  
  347.     cv::Mat FeaturesMap;    
  348.     cv::Mat z = RectTools::subwindow(image, extracted_roi, cv::BORDER_REPLICATE);  
  349.       
  350.     // 按照比例缩小边界大小  
  351.     if (z.cols != _tmpl_sz.width || z.rows != _tmpl_sz.height) {  
  352.         cv::resize(z, z, _tmpl_sz);  
  353.     }     
  354.   
  355.     // HOG features  
  356.     // 提取HOG特征点  
  357.     if (_hogfeatures) {  
  358.         IplImage z_ipl = z;  
  359.         CvLSVMFeatureMapCaskade *map;                                   // 申请指针  
  360.         getFeatureMaps(&z_ipl, cell_size, &map);            // 给map进行赋值  
  361.         normalizeAndTruncate(map,0.2f);                             // 归一化  
  362.         PCAFeatureMaps(map);                                                    // 由HOG特征变为PCA-HOG  
  363.         size_patch[0] = map->sizeY;  
  364.         size_patch[1] = map->sizeX;  
  365.         size_patch[2] = map->numFeatures;  
  366.   
  367.         FeaturesMap = cv::Mat(cv::Size(map->numFeatures,map->sizeX*map->sizeY), CV_32F, map->map);  // Procedure do deal with cv::Mat multichannel bug  
  368.         FeaturesMap = FeaturesMap.t();  
  369.         freeFeatureMapObject(&map);  
  370.   
  371.         // Lab features  
  372.         // 我测试结果,带有Lab特征在一些跟踪环节效果并不好  
  373.         if (_labfeatures) {  
  374.             cv::Mat imgLab;  
  375.             cvtColor(z, imgLab, CV_BGR2Lab);  
  376.             unsigned char *input = (unsigned char*)(imgLab.data);  
  377.   
  378.             // Sparse output vector  
  379.             cv::Mat outputLab = cv::Mat(_labCentroids.rows, size_patch[0]*size_patch[1], CV_32F, float(0));  
  380.   
  381.             int cntCell = 0;  
  382.             // Iterate through each cell  
  383.             for (int cY = cell_size; cY < z.rows-cell_size; cY+=cell_size){  
  384.                 for (int cX = cell_size; cX < z.cols-cell_size; cX+=cell_size){  
  385.                     // Iterate through each pixel of cell (cX,cY)  
  386.                     for(int y = cY; y < cY+cell_size; ++y){  
  387.                         for(int x = cX; x < cX+cell_size; ++x){  
  388.                             // Lab components for each pixel  
  389.                             float l = (float)input[(z.cols * y + x) * 3];  
  390.                             float a = (float)input[(z.cols * y + x) * 3 + 1];  
  391.                             float b = (float)input[(z.cols * y + x) * 3 + 2];  
  392.   
  393.                             // Iterate trough each centroid  
  394.                             float minDist = FLT_MAX;  
  395.                             int minIdx = 0;  
  396.                             float *inputCentroid = (float*)(_labCentroids.data);  
  397.                             for(int k = 0; k < _labCentroids.rows; ++k){  
  398.                                 float dist = ( (l - inputCentroid[3*k]) * (l - inputCentroid[3*k]) )  
  399.                                            + ( (a - inputCentroid[3*k+1]) * (a - inputCentroid[3*k+1]) )   
  400.                                            + ( (b - inputCentroid[3*k+2]) * (b - inputCentroid[3*k+2]) );  
  401.                                 if(dist < minDist){  
  402.                                     minDist = dist;  
  403.                                     minIdx = k;  
  404.                                 }  
  405.                             }  
  406.                             // Store result at output  
  407.                             outputLab.at<float>(minIdx, cntCell) += 1.0 / cell_sizeQ;   
  408.                             //((float*) outputLab.data)[minIdx * (size_patch[0]*size_patch[1]) + cntCell] += 1.0 / cell_sizeQ;   
  409.                         }  
  410.                     }  
  411.                     cntCell++;  
  412.                 }  
  413.             }  
  414.             // Update size_patch[2] and add features to FeaturesMap  
  415.             size_patch[2] += _labCentroids.rows;  
  416.             FeaturesMap.push_back(outputLab);  
  417.         }  
  418.     }  
  419.     else {  
  420.         FeaturesMap = RectTools::getGrayImage(z);  
  421.         FeaturesMap -= (float) 0.5; // In Paper;  
  422.         size_patch[0] = z.rows;  
  423.         size_patch[1] = z.cols;  
  424.         size_patch[2] = 1;    
  425.     }  
  426.       
  427.     if (inithann) {  
  428.         createHanningMats();  
  429.     }  
  430.     FeaturesMap = hann.mul(FeaturesMap);  
  431.     return FeaturesMap;  
  432. }  
  433.       
  434. // Initialize Hanning window. Function called only in the first frame.  
  435. // 初始化hanning窗,只执行一次,使用opencv函数做的  
  436. void KCFTracker::createHanningMats()  
  437. {     
  438.     cv::Mat hann1t = cv::Mat(cv::Size(size_patch[1],1), CV_32F, cv::Scalar(0));  
  439.     cv::Mat hann2t = cv::Mat(cv::Size(1,size_patch[0]), CV_32F, cv::Scalar(0));   
  440.   
  441.     for (int i = 0; i < hann1t.cols; i++)  
  442.         hann1t.at<float > (0, i) = 0.5 * (1 - std::cos(2 * 3.14159265358979323846 * i / (hann1t.cols - 1)));  
  443.     for (int i = 0; i < hann2t.rows; i++)  
  444.         hann2t.at<float > (i, 0) = 0.5 * (1 - std::cos(2 * 3.14159265358979323846 * i / (hann2t.rows - 1)));  
  445.   
  446.     cv::Mat hann2d = hann2t * hann1t;  
  447.     // HOG features  
  448.     if (_hogfeatures) {  
  449.         cv::Mat hann1d = hann2d.reshape(1,1); // Procedure do deal with cv::Mat multichannel bug  
  450.           
  451.         hann = cv::Mat(cv::Size(size_patch[0]*size_patch[1], size_patch[2]), CV_32F, cv::Scalar(0));  
  452.         for (int i = 0; i < size_patch[2]; i++) {  
  453.             for (int j = 0; j<size_patch[0]*size_patch[1]; j++) {  
  454.                 hann.at<float>(i,j) = hann1d.at<float>(0,j);  
  455.             }  
  456.         }  
  457.     }  
  458.     // Gray features  
  459.     else {  
  460.         hann = hann2d;  
  461.     }  
  462. }  
  463.   
  464. // Calculate sub-pixel peak for one dimension  
  465. // 使用幅值做差来定位峰值的位置,返回的是需要改变的偏移量大小  
  466. float KCFTracker::subPixelPeak(float left, float center, float right)  
  467. {     
  468.     float divisor = 2 * center - right - left;  
  469.   
  470.     if (divisor == 0)  
  471.         return 0;  
  472.       
  473.     return 0.5 * (right - left) / divisor;  
  474. }  


fhog.hpp:hog的相关函数

[cpp]  view plain  copy
  1. #ifndef _FHOG_H_  
  2. #define _FHOG_H_  
  3.   
  4. #include <stdio.h>  
  5. //#include "_lsvmc_types.h"  
  6. //#include "_lsvmc_error.h"  
  7. //#include "_lsvmc_routine.h"  
  8.   
  9. //#include "opencv2/imgproc.hpp"  
  10. #include "opencv2/imgproc/imgproc_c.h"  
  11.   
  12.   
  13. //modified from "_lsvmc_types.h"  
  14.   
  15. // DataType: STRUCT featureMap  
  16. // FEATURE MAP DESCRIPTION  
  17. //   Rectangular map (sizeX x sizeY),   
  18. //   every cell stores feature vector (dimension = numFeatures)  
  19. // map             - matrix of feature vectors  
  20. //                   to set and get feature vectors (i,j)   
  21. //                   used formula map[(j * sizeX + i) * p + k], where  
  22. //                   k - component of feature vector in cell (i, j)  
  23. typedef struct{  
  24.     int sizeX;  
  25.     int sizeY;  
  26.     int numFeatures;  
  27.     float *map;  
  28. } CvLSVMFeatureMapCaskade;  
  29.   
  30.   
  31. #include "float.h"  
## Tracking with Kernelized Correlation Filters Code author : Tomas Vojir ________________ This is a C++ reimplementation of algorithm presented in "High-Speed Tracking with Kernelized Correlation Filters" paper. For more info and implementation in other languages visit the [autor's webpage!](http://home.isr.uc.pt/~henriques/circulant/). It is extended by a scale estimation (use several *7* different scales steps) and by a RGB (channels) and Color Names [2] features. Data for Color Names features were obtained from [SAMF tracker](https://github.com/ihpdep/samf). It is free for research use. If you find it useful or use it in your research, please acknowledge my git repository and cite the original paper [1]. The code depends on OpenCV 2.4+ library and is build via cmake toolchain. _________________ Quick start guide for linux: open terminal in the directory with the code $ mkdir build; cd build; cmake .. ; make This code compiles into binary **kcf_vot** ./kcf_vot - using VOT 2014 methodology (http://www.votchallenge.net/) - INPUT : expecting two files, images.txt (list of sequence images with absolute path) and region.txt with initial bounding box in the first frame in format "top_left_x, top_left_y, width, height" or four corner points listed clockwise starting from bottom left corner. - OUTPUT : output.txt containing the bounding boxes in the format "top_left_x, top_left_y, width, height" ./kcf_trax - using VOT 2014+ trax protocol (http://www.votchallenge.net/) - require [trax](https://github.com/votchallenge/trax) library to be compiled with opencv support and installed. See trax instruction for compiling and installing. ___________ Performance | | **VOT2016 - baseline EAO** | **VOT2016 - unsupervised EAO** | [**TV77**](http://cmp.felk.cvut.cz/~vojirtom/dataset/index.html) Avg. Recall | |:---------------|:--------------:|:------------------:|:----------------:| | kcf |0.1530 | 0.3859 | 51% | | skcf |0.1661 | 0.4155 | 56% | | skcf-cn |0.178 | 0.4136 | 58% | | kcf-master |**0.1994** | **0.4376** | **63%** | __________ References [1] João F. Henriques, Rui Caseiro, Pedro Martins, Jorge Batista, “High-Speed Tracking with Kernelized Correlation Filters“, IEEE Transactions on Pattern Analysis and Machine Intelligence, 2015 [2] J. van de Weijer, C. Schmid, J. J. Verbeek, and D. Larlus. "Learning color names for real-world applications." TIP, 18(7):1512–1524, 2009. _____________________________________ Copyright (c) 2014, Tomáš Vojíř Permission to use, copy, modify, and distribute this software for research purposes is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. __________________ Additional Library NOTE: The following files are part of Piotr's Toolbox, and were modified for usage with c++ src/piotr_fhog/gradientMex.cpp src/piotr_fhog/sse.hpp src/piotr_fhog/wrappers.hpp You are encouraged to get the [full version of this library here.](http://vision.ucsd.edu/~pdollar/toolbox/doc/index.html) ______________________________________________________________________________ Copyright (c) 2012, Piotr Dollar All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project.
### 回答1: KCF是一种基于核的视觉跟踪算法,其通过学习目标的特征来实现对目标的跟踪。由于其高效性和准确性,KCF成为了目前最为流行的视觉跟踪算法之一。 在Matlab中,可以通过调用KCF的相关函数来实现对目标的跟踪。一般而言,使用KCF进行跟踪的过程可以分为以下几个步骤: 1. 初始化目标 首先需要定义跟踪目标,并选定一个合适的区域作为初始跟踪区域。 2. 提取特征 利用HOG等特征提取方法将目标区域进行特征提取,得到目标的特征描述符。 3. 计算核矩阵 通过将不同卷积核作用于目标的特征描述符,计算其对应的核矩阵,得到了目标的特征响应图。 4. 最大响应点定位 在特征响应图中,找到最大响应点,并以此为中心,选定一个新的目标区域。 5. 更新跟踪模型 利用新的目标区域和之前的跟踪模型,更新跟踪模型的参数,以便于跟踪目标在后续帧中的位置。 以上就是利用KCF算法在Matlab中实现目标跟踪的一般流程。针对不同的应用场景,还可以根据需要对算法进行一定的调整和优化。 ### 回答2: KCF代码是基于MATLAB的一种目标跟踪算法,通过对目标图像进行特征提取和运动预测来完成目标跟踪任务。该算法基于离散傅里叶变换(DFT)计算,因此具有快速速度和较高的稳定性。 KCF代码的实现主要分为以下几个步骤:首先进行图像预处理,对图像进行滤波、归一化等操作,以减少误差的影响;接着进行特征提取,这里采用的是HOG特征提取算法,可使目标图像的特征更加准确;然后进行傅里叶变换,将特征映射到频域中,再通过核函数对目标进行预测和跟踪;最后根据跟踪结果进行后续处理,包括图像展示、目标位置更新等。 总的来说,KCF代码是一种高效、可靠的目标跟踪算法,具有较高的准确率和实时性,可广泛应用于人脸识别、物体追踪等领域。 ### 回答3: KCF是一种卷积核相关滤波算法,它是一种效果非常好的目标跟踪算法。Matlab作为一种强大的编程语言与计算工具,可以用来实现KCF算法。 在Matlab中,通过对图像进行预处理,提取特征并使用KCF算法进行目标跟踪。具体步骤如下: 1.预处理:将原始图像转换为灰度图像,然后根据用户需求对图像进行裁剪; 2.提取特征:为了获得更好的跟踪效果,需要选择一种适合的特征提取方法。在这里,可以使用Hog特征或者深度神经网络提取特征; 3.训练模型:将第一帧图像中的对象位置以及提取的特征作为初始输入,使用KCF算法进行训练,获得优秀的模型; 4.跟踪目标:在剩下的帧中,根据上一帧的目标位置以及新的特征,使用KCF算法进行跟踪。 在实现KCF算法的时候,可以使用现成的开源代码库,比如MATLAB Computer Vision Toolbox和OpenCV等。同时,要注意调参和优化算法,以提高算法的准确性和效率。 总之,KCF是一种非常优秀的目标跟踪算法,Matlab是一种高效而强大的编程语言,二者的结合可以实现跟踪等强大的图像处理任务。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值