KCF跟踪源码-带注释

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jacke121/article/details/54315050

原文: http://blog.csdn.net/bisheng250/article/details/53672247?_t_t_t=0.27866495959460735

其中多尺度主要定义在kcftracker.cpp文件中的KCFTracker::update函数里面,通过检测一个大点一个小点的尺度,比较三个峰值的结果来进行多尺度的适应,简单,高效,改动少。


代码链接在这


tracker.h:定义Tracker类

  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

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

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

  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);  
  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的相关函数

  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"  
  32.   
  33. #define PI    CV_PI  
  34.   
  35. #define EPS 0.000001  
  36.   
  37. #define F_MAX FLT_MAX  
  38. #define F_MIN -FLT_MAX  
  39.   
  40. // The number of elements in bin  
  41. // The number of sectors in gradient histogram building  
  42. #define NUM_SECTOR 9  
  43.   
  44. // The number of levels in image resize procedure  
  45. // We need Lambda levels to resize image twice  
  46. #define LAMBDA 10  
  47.   
  48. // Block size. Used in feature pyramid building procedure  
  49. #define SIDE_LENGTH 8  
  50.   
  51. #define VAL_OF_TRUNCATE 0.2f   
  52.   
  53.   
  54. //modified from "_lsvm_error.h"  
  55. #define LATENT_SVM_OK 0  
  56. #define LATENT_SVM_MEM_NULL 2  
  57. #define DISTANCE_TRANSFORM_OK 1  
  58. #define DISTANCE_TRANSFORM_GET_INTERSECTION_ERROR -1  
  59. #define DISTANCE_TRANSFORM_ERROR -2  
  60. #define DISTANCE_TRANSFORM_EQUAL_POINTS -3  
  61. #define LATENT_SVM_GET_FEATURE_PYRAMID_FAILED -4  
  62. #define LATENT_SVM_SEARCH_OBJECT_FAILED -5  
  63. #define LATENT_SVM_FAILED_SUPERPOSITION -6  
  64. #define FILTER_OUT_OF_BOUNDARIES -7  
  65. #define LATENT_SVM_TBB_SCHEDULE_CREATION_FAILED -8  
  66. #define LATENT_SVM_TBB_NUMTHREADS_NOT_CORRECT -9  
  67. #define FFT_OK 2  
  68. #define FFT_ERROR -10  
  69. #define LSVM_PARSER_FILE_NOT_FOUND -11  
  70.   
  71.   
  72.   
  73. /* 
  74. // Getting feature map for the selected subimage   
  75. // 
  76. // API 
  77. // int getFeatureMaps(const IplImage * image, const int k, featureMap **map); 
  78. // INPUT 
  79. // image             - selected subimage 
  80. // k                 - size of cells 
  81. // OUTPUT 
  82. // map               - feature map 
  83. // RESULT 
  84. // Error status 
  85. */  
  86. int getFeatureMaps(const IplImage * image, const int k, CvLSVMFeatureMapCaskade **map);  
  87.   
  88.   
  89. /* 
  90. // Feature map Normalization and Truncation  
  91. // 
  92. // API 
  93. // int normalizationAndTruncationFeatureMaps(featureMap *map, const float alfa); 
  94. // INPUT 
  95. // map               - feature map 
  96. // alfa              - truncation threshold 
  97. // OUTPUT 
  98. // map               - truncated and normalized feature map 
  99. // RESULT 
  100. // Error status 
  101. */  
  102. int normalizeAndTruncate(CvLSVMFeatureMapCaskade *map, const float alfa);  
  103.   
  104. /* 
  105. // Feature map reduction 
  106. // In each cell we reduce dimension of the feature vector 
  107. // according to original paper special procedure 
  108. // 
  109. // API 
  110. // int PCAFeatureMaps(featureMap *map) 
  111. // INPUT 
  112. // map               - feature map 
  113. // OUTPUT 
  114. // map               - feature map 
  115. // RESULT 
  116. // Error status 
  117. */  
  118. int PCAFeatureMaps(CvLSVMFeatureMapCaskade *map);  
  119.   
  120.   
  121. //modified from "lsvmc_routine.h"  
  122.   
  123. int allocFeatureMapObject(CvLSVMFeatureMapCaskade **obj, const int sizeX, const int sizeY,  
  124.                           const int p);  
  125.   
  126. int freeFeatureMapObject (CvLSVMFeatureMapCaskade **obj);  
  127.   
  128.   
  129. #endif  

fhog.cpp:fhog的相关函数定义
  1. #include "fhog.hpp"  
  2.   
  3.   
  4. #ifdef HAVE_TBB  
  5. #include <tbb/tbb.h>  
  6. #include "tbb/parallel_for.h"  
  7. #include "tbb/blocked_range.h"  
  8. #endif  
  9.   
  10. #ifndef max  
  11. #define max(a,b)            (((a) > (b)) ? (a) : (b))  
  12. #endif  
  13.   
  14. #ifndef min  
  15. #define min(a,b)            (((a) < (b)) ? (a) : (b))  
  16. #endif  
  17.   
  18.   
  19. /* 
  20. // Getting feature map for the selected subimage 
  21. // 
  22. // API 
  23. // int getFeatureMaps(const IplImage * image, const int k, featureMap **map); 
  24. // INPUT 
  25. // image             - selected subimage 
  26. // k                 - size of cells 
  27. // OUTPUT 
  28. // map               - feature map 
  29. // RESULT 
  30. // Error status 
  31. */  
  32. int getFeatureMaps(const IplImage* image, const int k, CvLSVMFeatureMapCaskade **map)  
  33. {  
  34.     int sizeX, sizeY;  
  35.     int p, px, stringSize;  
  36.     int height, width, numChannels;  
  37.     int i, j, kk, c, ii, jj, d;  
  38.     float  * datadx, * datady;  
  39.   
  40.     int   ch;  
  41.     float magnitude, x, y, tx, ty;  
  42.   
  43.     IplImage * dx, * dy;  
  44.     int *nearest;  
  45.     float *w, a_x, b_x;  
  46.   
  47.     // 横向和纵向的3长度{-1,0,1}矩阵  
  48.     float kernel[3] = {-1.f, 0.f, 1.f};  
  49.     CvMat kernel_dx = cvMat(1, 3, CV_32F, kernel);          // 1*3的矩阵  
  50.     CvMat kernel_dy = cvMat(3, 1, CV_32F, kernel);          // 3*1的矩阵  
  51.   
  52.     float * r;  
  53.     int   * alfa;  
  54.   
  55.     float boundary_x[NUM_SECTOR + 1];                       // boundary_x[10]  
  56.     float boundary_y[NUM_SECTOR + 1];  
  57.     float max, dotProd;  
  58.     int   maxi;  
  59.   
  60.     height = image->height;  
  61.     width  = image->width ;  
  62.   
  63.     numChannels = image->nChannels;  
  64.   
  65.     // 采样图像大小的Ipl图像  
  66.     dx    = cvCreateImage(cvSize(image->width, image->height),  
  67.                           IPL_DEPTH_32F, 3);  
  68.     dy    = cvCreateImage(cvSize(image->width, image->height),  
  69.                           IPL_DEPTH_32F, 3);  
  70.   
  71.     // 向下取整的(边界大小/4),k = cell_size  
  72.     sizeX = width  / k;  
  73.     sizeY = height / k;  
  74.     px    = 3 * NUM_SECTOR;     // px=3*9=27  
  75.     p     = px;  
  76.     stringSize = sizeX * p;     // stringSize = 27*sizeX  
  77.     allocFeatureMapObject(map, sizeX, sizeY, p);  
  78.   
  79.   
  80.     // image:输入图像.  
  81.     // dx:输出图像.  
  82.     // kernel_dx:卷积核, 单通道浮点矩阵. 如果想要应用不同的核于不同的通道,先用 cvSplit 函数分解图像到单个色彩通道上,然后单独处理。  
  83.     // cvPoint(-1, 0):核的锚点表示一个被滤波的点在核内的位置。 锚点应该处于核内部。缺省值 (-1,-1) 表示锚点在核中心。  
  84.     // 函数 cvFilter2D 对图像进行线性滤波,支持 In-place 操作。当核运算部分超出输入图像时,函数从最近邻的图像内部象素差值得到边界外面的象素值。  
  85.     cvFilter2D(image, dx, &kernel_dx, cvPoint(-1, 0));      // 起点在(x-1,y),按x方向滤波  
  86.     cvFilter2D(image, dy, &kernel_dy, cvPoint(0, -1));      // 起点在(x,y-1),按y方向滤波  
  87.   
  88.     // 初始化cos和sin函数  
  89.     float arg_vector;  
  90.     for(i = 0; i <= NUM_SECTOR; i++)  
  91.     {  
  92.         arg_vector    = ( (float) i ) * ( (float)(PI) / (float)(NUM_SECTOR) );  
  93.         boundary_x[i] = cosf(arg_vector);  
  94.         boundary_y[i] = sinf(arg_vector);  
  95.     }/*for(i = 0; i <= NUM_SECTOR; i++) */  
  96.   
  97.     r    = (float *)malloc( sizeof(float) * (width * height));  
  98.     alfa = (int   *)malloc( sizeof(int  ) * (width * height * 2));  
  99.   
  100.     for(j = 1; j < height - 1; j++)  
  101.     {  
  102.         // 每一行起点  
  103.         datadx = (float*)(dx->imageData + dx->widthStep * j);  
  104.         datady = (float*)(dy->imageData + dy->widthStep * j);  
  105.   
  106.         // 遍历该行每一个元素  
  107.         for(i = 1; i < width - 1; i++)  
  108.         {  
  109.             // 第一颜色通道  
  110.             c = 0;  
  111.             x = (datadx[i * numChannels + c]);  
  112.             y = (datady[i * numChannels + c]);  
  113.   
  114.             r[j * width + i] =sqrtf(x * x + y * y);  
  115.   
  116.             // 使用向量大小最大的通道替代储存值  
  117.             for(ch = 1; ch < numChannels; ch++)  
  118.             {  
  119.                 tx = (datadx[i * numChannels + ch]);  
  120.                 ty = (datady[i * numChannels + ch]);  
  121.                 magnitude = sqrtf(tx * tx + ty * ty);  
  122.                 if(magnitude > r[j * width + i])  
  123.                 {  
  124.                     r[j * width + i] = magnitude;  
  125.                     c = ch;  
  126.                     x = tx;  
  127.                     y = ty;  
  128.                 }  
  129.             }/*for(ch = 1; ch < numChannels; ch++)*/  
  130.   
  131.             // 使用sqrt(cos*x*cos*x+sin*y*sin*y)最大的替换掉  
  132.             max  = boundary_x[0] * x + boundary_y[0] * y;   // max = 1*x+0*y;  
  133.             maxi = 0;  
  134.             for (kk = 0; kk < NUM_SECTOR; kk++)  
  135.             {  
  136.                 dotProd = boundary_x[kk] * x + boundary_y[kk] * y;  
  137.                 if (dotProd > max)  
  138.                 {  
  139.                     max  = dotProd;  
  140.                     maxi = kk;  
  141.                 }  
  142.                 else  
  143.                 {  
  144.                     if (-dotProd > max)  
  145.                     {  
  146.                         max  = -dotProd;  
  147.                         maxi = kk + NUM_SECTOR;             // 周期的,所以+一个周期NUM_SECTOR  
  148.                     }  
  149.                 }  
  150.             }  
  151.             // 看起来有点像储存cos和sin的周期值  
  152.             alfa[j * width * 2 + i * 2    ] = maxi % NUM_SECTOR;  
  153.             alfa[j * width * 2 + i * 2 + 1] = maxi;  
  154.         }/*for(i = 0; i < width; i++)*/  
  155.     }/*for(j = 0; j < height; j++)*/  
  156.   
  157.     nearest = (int  *)malloc(sizeof(int  ) *  k);  
  158.     w       = (float*)malloc(sizeof(float) * (k * 2));  
  159.   
  160.     // nearest=[-1,-1,1,1];  
  161.     for(i = 0; i < k / 2; i++)  
  162.     {  
  163.         nearest[i] = -1;  
  164.     }/*for(i = 0; i < k / 2; i++)*/  
  165.     for(i = k / 2; i < k; i++)  
  166.     {  
  167.         nearest[i] = 1;  
  168.     }/*for(i = k / 2; i < k; i++)*/  
  169.   
  170.     // 这算的都是啥?我怎么没在算法上看见这一段???  
  171.     //        1/a          1/b  
  172.     // w[1]=_______  w[2]=_______  
  173.     //      1/a+1/b       1/a+1/b  
  174.     for(j = 0; j < k / 2; j++)  
  175.     {  
  176.         b_x = k / 2 + j + 0.5f;  
  177.         a_x = k / 2 - j - 0.5f;  
  178.         w[j * 2    ] = 1.0f/a_x * ((a_x * b_x) / ( a_x + b_x));  
  179.         w[j * 2 + 1] = 1.0f/b_x * ((a_x * b_x) / ( a_x + b_x));  
  180.     }/*for(j = 0; j < k / 2; j++)*/  
  181.     for(j = k / 2; j < k; j++)  
  182.     {  
  183.         a_x = j - k / 2 + 0.5f;  
  184.         b_x =-j + k / 2 - 0.5f + k;  
  185.         w[j * 2    ] = 1.0f/a_x * ((a_x * b_x) / ( a_x + b_x));  
  186.         w[j * 2 + 1] = 1.0f/b_x * ((a_x * b_x) / ( a_x + b_x));  
  187.     }/*for(j = k / 2; j < k; j++)*/  
  188.   
  189.     // 计算梯度的公式好像和算法不太一样,应该是经过了某种离奇的推倒  
  190.     for(i = 0; i < sizeY; i++)  
  191.     {  
  192.       for(j = 0; j < sizeX; j++)  
  193.       {  
  194.         for(ii = 0; ii < k; ii++)  
  195.         {  
  196.           for(jj = 0; jj < k; jj++)  
  197.           {  
  198.             if ((i * k + ii > 0) &&  
  199.                 (i * k + ii < height - 1) &&  
  200.                 (j * k + jj > 0) &&  
  201.                 (j * k + jj < width  - 1))  
  202.             {  
  203.               d = (k * i + ii) * width + (j * k + jj);  
  204.               (*map)->map[ i * stringSize + j * (*map)->numFeatures + alfa[d * 2    ]] +=  
  205.                   r[d] * w[ii * 2] * w[jj * 2];  
  206.               (*map)->map[ i * stringSize + j * (*map)->numFeatures + alfa[d * 2 + 1] + NUM_SECTOR] +=  
  207.                   r[d] * w[ii * 2] * w[jj * 2];  
  208.               if ((i + nearest[ii] >= 0) &&  
  209.                   (i + nearest[ii] <= sizeY - 1))  
  210.               {  
  211.                 (*map)->map[(i + nearest[ii]) * stringSize + j * (*map)->numFeatures + alfa[d * 2    ]             ] +=  
  212.                   r[d] * w[ii * 2 + 1] * w[jj * 2 ];  
  213.                 (*map)->map[(i + nearest[ii]) * stringSize + j * (*map)->numFeatures + alfa[d * 2 + 1] + NUM_SECTOR] +=  
  214.                   r[d] * w[ii * 2 + 1] * w[jj * 2 ];  
  215.               }  
  216.               if ((j + nearest[jj] >= 0) &&  
  217.                   (j + nearest[jj] <= sizeX - 1))  
  218.               {  
  219.                 (*map)->map[i * stringSize + (j + nearest[jj]) * (*map)->numFeatures + alfa[d * 2    ]             ] +=  
  220.                   r[d] * w[ii * 2] * w[jj * 2 + 1];  
  221.                 (*map)->map[i * stringSize + (j + nearest[jj]) * (*map)->numFeatures + alfa[d * 2 + 1] + NUM_SECTOR] +=  
  222.                   r[d] * w[ii * 2] * w[jj * 2 + 1];  
  223.               }  
  224.               if ((i + nearest[ii] >= 0) &&  
  225.                   (i + nearest[ii] <= sizeY - 1) &&  
  226.                   (j + nearest[jj] >= 0) &&  
  227.                   (j + nearest[jj] <= sizeX - 1))  
  228.               {  
  229.                 (*map)->map[(i + nearest[ii]) * stringSize + (j + nearest[jj]) * (*map)->numFeatures + alfa[d * 2    ]             ] +=  
  230.                   r[d] * w[ii * 2 + 1] * w[jj * 2 + 1];  
  231.                 (*map)->map[(i + nearest[ii]) * stringSize + (j + nearest[jj]) * (*map)->numFeatures + alfa[d * 2 + 1] + NUM_SECTOR] +=  
  232.                   r[d] * w[ii * 2 + 1] * w[jj * 2 + 1];  
  233.               }  
  234.             }  
  235.           }/*for(jj = 0; jj < k; jj++)*/  
  236.         }/*for(ii = 0; ii < k; ii++)*/  
  237.       }/*for(j = 1; j < sizeX - 1; j++)*/  
  238.     }/*for(i = 1; i < sizeY - 1; i++)*/  
  239.   
  240.     // 释放变量  
  241.     cvReleaseImage(&dx);  
  242.     cvReleaseImage(&dy);  
  243.   
  244.   
  245.     free(w);  
  246.     free(nearest);  
  247.   
  248.     free(r);  
  249.     free(alfa);  
  250.   
  251.     return LATENT_SVM_OK;  
  252. }  
  253.   
  254. /* 
  255. // Feature map Normalization and Truncation 
  256. // 
  257. // API 
  258. // int normalizeAndTruncate(featureMap *map, const float alfa); 
  259. // INPUT 
  260. // map               - feature map 
  261. // alfa              - truncation threshold 
  262. // OUTPUT 
  263. // map               - truncated and normalized feature map 
  264. // RESULT 
  265. // Error status 
  266. */  
  267. //  
  268. int normalizeAndTruncate(CvLSVMFeatureMapCaskade *map, const float alfa)  
  269. {  
  270.     int i,j, ii;  
  271.     int sizeX, sizeY, p, pos, pp, xp, pos1, pos2;  
  272.     float * partOfNorm; // norm of C(i, j)  
  273.     float * newData;  
  274.     float   valOfNorm;  
  275.   
  276.     sizeX     = map->sizeX;  
  277.     sizeY     = map->sizeY;  
  278.     partOfNorm = (float *)malloc (sizeof(float) * (sizeX * sizeY));  
  279.   
  280.     p  = NUM_SECTOR;  
  281.     xp = NUM_SECTOR * 3;  
  282.     pp = NUM_SECTOR * 12;  
  283.   
  284.     for(i = 0; i < sizeX * sizeY; i++)  
  285.     {  
  286.         valOfNorm = 0.0f;  
  287.         pos = i * map->numFeatures;  
  288.         for(j = 0; j < p; j++)  
  289.         {  
  290.             valOfNorm += map->map[pos + j] * map->map[pos + j];  
  291.         }/*for(j = 0; j < p; j++)*/  
  292.         partOfNorm[i] = valOfNorm;  
  293.     }/*for(i = 0; i < sizeX * sizeY; i++)*/  
  294.   
  295.     sizeX -= 2;  
  296.     sizeY -= 2;  
  297.   
  298.     newData = (float *)malloc (sizeof(float) * (sizeX * sizeY * pp));  
  299. //normalization  
  300.     for(i = 1; i <= sizeY; i++)  
  301.     {  
  302.         for(j = 1; j <= sizeX; j++)  
  303.         {  
  304.             valOfNorm = sqrtf(  
  305.                 partOfNorm[(i    )*(sizeX + 2) + (j    )] +  
  306.                 partOfNorm[(i    )*(sizeX + 2) + (j + 1)] +  
  307.                 partOfNorm[(i + 1)*(sizeX + 2) + (j    )] +  
  308.                 partOfNorm[(i + 1)*(sizeX + 2) + (j + 1)]) + FLT_EPSILON;  
  309.             pos1 = (i  ) * (sizeX + 2) * xp + (j  ) * xp;  
  310.             pos2 = (i-1) * (sizeX    ) * pp + (j-1) * pp;  
  311.             for(ii = 0; ii < p; ii++)  
  312.             {  
  313.                 newData[pos2 + ii        ] = map->map[pos1 + ii    ] / valOfNorm;  
  314.             }/*for(ii = 0; ii < p; ii++)*/  
  315.             for(ii = 0; ii < 2 * p; ii++)  
  316.             {  
  317.                 newData[pos2 + ii + p * 4] = map->map[pos1 + ii + p] / valOfNorm;  
  318.             }/*for(ii = 0; ii < 2 * p; ii++)*/  
  319.             valOfNorm = sqrtf(  
  320.                 partOfNorm[(i    )*(sizeX + 2) + (j    )] +  
  321.                 partOfNorm[(i    )*(sizeX + 2) + (j + 1)] +  
  322.                 partOfNorm[(i - 1)*(sizeX + 2) + (j    )] +  
  323.                 partOfNorm[(i - 1)*(sizeX + 2) + (j + 1)]) + FLT_EPSILON;  
  324.             for(ii = 0; ii < p; ii++)  
  325.             {  
  326.                 newData[pos2 + ii + p    ] = map->map[pos1 + ii    ] / valOfNorm;  
  327.             }/*for(ii = 0; ii < p; ii++)*/  
  328.             for(ii = 0; ii < 2 * p; ii++)  
  329.             {  
  330.                 newData[pos2 + ii + p * 6] = map->map[pos1 + ii + p] / valOfNorm;  
  331.             }/*for(ii = 0; ii < 2 * p; ii++)*/  
  332.             valOfNorm = sqrtf(  
  333.                 partOfNorm[(i    )*(sizeX + 2) + (j    )] +  
  334.                 partOfNorm[(i    )*(sizeX + 2) + (j - 1)] +  
  335.                 partOfNorm[(i + 1)*(sizeX + 2) + (j    )] +  
  336.                 partOfNorm[(i + 1)*(sizeX + 2) + (j - 1)]) + FLT_EPSILON;  
  337.             for(ii = 0; ii < p; ii++)  
  338.             {  
  339.                 newData[pos2 + ii + p * 2] = map->map[pos1 + ii    ] / valOfNorm;  
  340.             }/*for(ii = 0; ii < p; ii++)*/  
  341.             for(ii = 0; ii < 2 * p; ii++)  
  342.             {  
  343.                 newData[pos2 + ii + p * 8] = map->map[pos1 + ii + p] / valOfNorm;  
  344.             }/*for(ii = 0; ii < 2 * p; ii++)*/  
  345.             valOfNorm = sqrtf(  
  346.                 partOfNorm[(i    )*(sizeX + 2) + (j    )] +  
  347.                 partOfNorm[(i    )*(sizeX + 2) + (j - 1)] +  
  348.                 partOfNorm[(i - 1)*(sizeX + 2) + (j    )] +  
  349.                 partOfNorm[(i - 1)*(sizeX + 2) + (j - 1)]) + FLT_EPSILON;  
  350.             for(ii = 0; ii < p; ii++)  
  351.             {  
  352.                 newData[pos2 + ii + p * 3 ] = map->map[pos1 + ii    ] / valOfNorm;  
  353.             }/*for(ii = 0; ii < p; ii++)*/  
  354.             for(ii = 0; ii < 2 * p; ii++)  
  355.             {  
  356.                 newData[pos2 + ii + p * 10] = map->map[pos1 + ii + p] / valOfNorm;  
  357.             }/*for(ii = 0; ii < 2 * p; ii++)*/  
  358.         }/*for(j = 1; j <= sizeX; j++)*/  
  359.     }/*for(i = 1; i <= sizeY; i++)*/  
  360. //truncation  
  361.     for(i = 0; i < sizeX * sizeY * pp; i++)  
  362.     {  
  363.         if(newData [i] > alfa) newData [i] = alfa;  
  364.     }/*for(i = 0; i < sizeX * sizeY * pp; i++)*/  
  365. //swop data  
  366.   
  367.     map->numFeatures  = pp;  
  368.     map->sizeX = sizeX;  
  369.     map->sizeY = sizeY;  
  370.   
  371.     free (map->map);  
  372.     free (partOfNorm);  
  373.   
  374.     map->map = newData;  
  375.   
  376.     return LATENT_SVM_OK;  
  377. }  
  378. /* 
  379. // Feature map reduction 
  380. // In each cell we reduce dimension of the feature vector 
  381. // according to original paper special procedure 
  382. // 
  383. // API 
  384. // int PCAFeatureMaps(featureMap *map) 
  385. // INPUT 
  386. // map               - feature map 
  387. // OUTPUT 
  388. // map               - feature map 
  389. // RESULT 
  390. // Error status 
  391. */  
  392. int PCAFeatureMaps(CvLSVMFeatureMapCaskade *map)  
  393. {  
  394.     int i,j, ii, jj, k;  
  395.     int sizeX, sizeY, p,  pp, xp, yp, pos1, pos2;  
  396.     float * newData;  
  397.     float val;  
  398.     float nx, ny;  
  399.   
  400.     // 初始化Hog所需要的参数  
  401.     sizeX = map->sizeX;  
  402.     sizeY = map->sizeY;  
  403.     p     = map->numFeatures;           // 3*9  
  404.     pp    = NUM_SECTOR * 3 + 4;         // 9*3+4  
  405.     yp    = 4;  
  406.     xp    = NUM_SECTOR;  
  407.   
  408.     nx    = 1.0f / sqrtf((float)(xp * 2));  
  409.     ny    = 1.0f / sqrtf((float)(yp    ));  
  410.   
  411.     // 新建一个map->map的指针  
  412.     newData = (float *)malloc (sizeof(float) * (sizeX * sizeY * pp));  
  413.   
  414.     for(i = 0; i < sizeY; i++)  
  415.     {  
  416.         for(j = 0; j < sizeX; j++)  
  417.         {  
  418.             pos1 = ((i)*sizeX + j)*p;  
  419.             pos2 = ((i)*sizeX + j)*pp;  
  420.             k = 0;  
  421.             for(jj = 0; jj < xp * 2; jj++)  
  422.             {  
  423.                 val = 0;  
  424.                 for(ii = 0; ii < yp; ii++)  
  425.                 {  
  426.                     val += map->map[pos1 + yp * xp + ii * xp * 2 + jj];  
  427.                 }/*for(ii = 0; ii < yp; ii++)*/  
  428.                 newData[pos2 + k] = val * ny;  
  429.                 k++;  
  430.             }/*for(jj = 0; jj < xp * 2; jj++)*/  
  431.             for(jj = 0; jj < xp; jj++)  
  432.             {  
  433.                 val = 0;  
  434.                 for(ii = 0; ii < yp; ii++)  
  435.                 {  
  436.                     val += map->map[pos1 + ii * xp + jj];  
  437.                 }/*for(ii = 0; ii < yp; ii++)*/  
  438.                 newData[pos2 + k] = val * ny;  
  439.                 k++;  
  440.             }/*for(jj = 0; jj < xp; jj++)*/  
  441.             for(ii = 0; ii < yp; ii++)  
  442.             {  
  443.                 val = 0;  
  444.                 for(jj = 0; jj < 2 * xp; jj++)  
  445.                 {  
  446.                     val += map->map[pos1 + yp * xp + ii * xp * 2 + jj];  
  447.                 }/*for(jj = 0; jj < xp; jj++)*/  
  448.                 newData[pos2 + k] = val * nx;  
  449.                 k++;  
  450.             } /*for(ii = 0; ii < yp; ii++)*/  
  451.         }/*for(j = 0; j < sizeX; j++)*/  
  452.     }/*for(i = 0; i < sizeY; i++)*/  
  453. //swop data  
  454.   
  455.     // 将计算结果,指针复制到结果输出的map上  
  456.     map->numFeatures = pp;  
  457.   
  458.     free (map->map);  
  459.   
  460.     map->map = newData;  
  461.   
  462.     return LATENT_SVM_OK;       // return 0  
  463. }  
  464.   
  465.   
  466. //modified from "lsvmc_routine.cpp"  
  467. // 根据输入,转换成指针**obj,其中(*obj)->map为sizeX * sizeY  * numFeatures大小  
  468. int allocFeatureMapObject(CvLSVMFeatureMapCaskade **obj, const int sizeX,  
  469.                           const int sizeY, const int numFeatures)  
  470. {  
  471.     int i;  
  472.     (*obj) = (CvLSVMFeatureMapCaskade *)malloc(sizeof(CvLSVMFeatureMapCaskade));  
  473.     (*obj)->sizeX       = sizeX;  
  474.     (*obj)->sizeY       = sizeY;  
  475.     (*obj)->numFeatures = numFeatures;          // 27  
  476.     (*obj)->map = (float *) malloc(sizeof (float) *  
  477.                                   (sizeX * sizeY  * numFeatures));  
  478.     for(i = 0; i < sizeX * sizeY * numFeatures; i++)  
  479.     {  
  480.         (*obj)->map[i] = 0.0f;  
  481.     }  
  482.     return LATENT_SVM_OK;  
  483. }  
  484.   
  485.   
  486. // 释放自己定义的CvLSVMFeatureMapCaskade数据  
  487. int freeFeatureMapObject (CvLSVMFeatureMapCaskade **obj)  
  488. {  
  489.     if(*obj == NULL) return LATENT_SVM_MEM_NULL;  
  490.     free((*obj)->map);  
  491.     free(*obj);  
  492.     (*obj) = NULL;  
  493.     return LATENT_SVM_OK;  
  494. }  

ffttools.hpp
  1. #pragma once  
  2.   
  3. //#include <cv.h>  
  4.   
  5. #ifndef _OPENCV_FFTTOOLS_HPP_  
  6. #define _OPENCV_FFTTOOLS_HPP_  
  7. #endif  
  8.   
  9. //NOTE: FFTW support is still shaky, disabled for now.  
  10. /*#ifdef USE_FFTW 
  11. #include <fftw3.h> 
  12. #endif*/  
  13.   
  14. namespace FFTTools  
  15. {  
  16. // Previous declarations, to avoid warnings  
  17. cv::Mat fftd(cv::Mat img, bool backwards = false);  
  18. cv::Mat real(cv::Mat img);  
  19. cv::Mat imag(cv::Mat img);  
  20. cv::Mat magnitude(cv::Mat img);  
  21. cv::Mat complexMultiplication(cv::Mat a, cv::Mat b);  
  22. cv::Mat complexDivision(cv::Mat a, cv::Mat b);  
  23. void rearrange(cv::Mat &img);  
  24. void normalizedLogTransform(cv::Mat &img);  
  25.   
  26.   
  27. // 做dfft  
  28. cv::Mat fftd(cv::Mat img, bool backwards)  
  29. {  
  30. /* 
  31. #ifdef USE_FFTW 
  32.  
  33.     fftw_complex * fm = (fftw_complex*) fftw_malloc(sizeof (fftw_complex) * img.cols * img.rows); 
  34.  
  35.     fftw_plan p = fftw_plan_dft_2d(img.rows, img.cols, fm, fm, backwards ? 1 : -1, 0 * FFTW_ESTIMATE); 
  36.  
  37.  
  38.     if (img.channels() == 1) 
  39.     { 
  40.         for (int i = 0; i < img.rows; i++) 
  41.             for (int j = 0; j < img.cols; j++) 
  42.             { 
  43.                 fm[i * img.cols + j][0] = img.at<float>(i, j); 
  44.                 fm[i * img.cols + j][1] = 0; 
  45.             } 
  46.     } 
  47.     else 
  48.     { 
  49.         assert(img.channels() == 2); 
  50.         for (int i = 0; i < img.rows; i++) 
  51.             for (int j = 0; j < img.cols; j++) 
  52.             { 
  53.                 fm[i * img.cols + j][0] = img.at<cv::Vec2d > (i, j)[0]; 
  54.                 fm[i * img.cols + j][1] = img.at<cv::Vec2d > (i, j)[1]; 
  55.             } 
  56.     } 
  57.     fftw_execute(p); 
  58.     cv::Mat res(img.rows, img.cols, CV_64FC2); 
  59.  
  60.  
  61.     for (int i = 0; i < img.rows; i++) 
  62.         for (int j = 0; j < img.cols; j++) 
  63.         { 
  64.             res.at<cv::Vec2d > (i, j)[0] = fm[i * img.cols + j][0]; 
  65.             res.at<cv::Vec2d > (i, j)[1] = fm[i * img.cols + j][1]; 
  66.  
  67.             //  _iout(fm[i * img.cols + j][0]); 
  68.         } 
  69.  
  70.     if (backwards)res *= 1.d / (float) (res.cols * res.rows); 
  71.  
  72.     fftw_free(p); 
  73.     fftw_free(fm); 
  74.     return res; 
  75.  
  76. #else 
  77. */  
  78.     if (img.channels() == 1)  
  79.     {  
  80.         cv::Mat planes[] = {cv::Mat_<float> (img), cv::Mat_<float>::zeros(img.size())};  
  81.         //cv::Mat planes[] = {cv::Mat_<double> (img), cv::Mat_<double>::zeros(img.size())};  
  82.         cv::merge(planes, 2, img);  
  83.     }  
  84.     cv::dft(img, img, backwards ? (cv::DFT_INVERSE | cv::DFT_SCALE) : 0 );  
  85.   
  86.     return img;  
  87.   
  88. /*#endif*/  
  89.   
  90. }  
  91.   
  92. // 图像实部  
  93. cv::Mat real(cv::Mat img)  
  94. {  
  95.     std::vector<cv::Mat> planes;  
  96.     cv::split(img, planes);  
  97.     return planes[0];  
  98. }  
  99.   
  100. // 图像虚部  
  101. cv::Mat imag(cv::Mat img)  
  102. {  
  103.     std::vector<cv::Mat> planes;  
  104.     cv::split(img, planes);  
  105.     return planes[1];  
  106. }  
  107.   
  108. // 复数的模  
  109. cv::Mat magnitude(cv::Mat img)  
  110. {  
  111.     cv::Mat res;  
  112.     std::vector<cv::Mat> planes;  
  113.     cv::split(img, planes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) 实部虚部分开  
  114.     if (planes.size() == 1) res = cv::abs(img);  
  115.     else if (planes.size() == 2) cv::magnitude(planes[0], planes[1], res); // planes[0] = magnitude 求复数的模(sqrt(x(I)^2+y(I)^2))  
  116.     else assert(0);  
  117.     return res;  
  118. }  
  119.   
  120. // 复数乘法  
  121. cv::Mat complexMultiplication(cv::Mat a, cv::Mat b)  
  122. {  
  123.     std::vector<cv::Mat> pa;  
  124.     std::vector<cv::Mat> pb;  
  125.     cv::split(a, pa);       //通道拆分  
  126.     cv::split(b, pb);       //通道拆分  
  127.   
  128.     std::vector<cv::Mat> pres;  
  129.     pres.push_back(pa[0].mul(pb[0]) - pa[1].mul(pb[1]));  
  130.     pres.push_back(pa[0].mul(pb[1]) + pa[1].mul(pb[0]));  
  131.   
  132.     cv::Mat res;  
  133.     cv::merge(pres, res);       //合并通道  
  134.   
  135.     return res;  
  136. }  
  137.   
  138. // 复数除法  
  139. cv::Mat complexDivision(cv::Mat a, cv::Mat b)  
  140. {  
  141.     std::vector<cv::Mat> pa;  
  142.     std::vector<cv::Mat> pb;  
  143.     cv::split(a, pa);       // 通道拆分  
  144.     cv::split(b, pb);       // 通道拆分  
  145.   
  146.     cv::Mat divisor = 1. / (pb[0].mul(pb[0]) + pb[1].mul(pb[1]));       // 实部虚部相乘求倒数  
  147.   
  148.     std::vector<cv::Mat> pres;  
  149.   
  150.     pres.push_back((pa[0].mul(pb[0]) + pa[1].mul(pb[1])).mul(divisor));  
  151.     pres.push_back((pa[1].mul(pb[0]) + pa[0].mul(pb[1])).mul(divisor));  
  152.   
  153.     cv::Mat res;  
  154.     cv::merge(pres, res);       // 合并通道  
  155.     return res;  
  156. }  
  157.   
  158. // 区域搬移  
  159. // 0 1 变成-> 3 2  
  160. // 2 3       1 0  
  161. void rearrange(cv::Mat &img)  
  162. {  
  163.     // img = img(cv::Rect(0, 0, img.cols & -2, img.rows & -2));  
  164.     int cx = img.cols / 2;  
  165.     int cy = img.rows / 2;  
  166.   
  167.     cv::Mat q0(img, cv::Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant  
  168.     cv::Mat q1(img, cv::Rect(cx, 0, cx, cy)); // Top-Right  
  169.     cv::Mat q2(img, cv::Rect(0, cy, cx, cy)); // Bottom-Left  
  170.     cv::Mat q3(img, cv::Rect(cx, cy, cx, cy)); // Bottom-Right  
  171.   
  172.     cv::Mat tmp; // swap quadrants (Top-Left with Bottom-Right)  
  173.     q0.copyTo(tmp);  
  174.     q3.copyTo(q0);  
  175.     tmp.copyTo(q3);  
  176.     q1.copyTo(tmp); // swap quadrant (Top-Right with Bottom-Left)  
  177.     q2.copyTo(q1);  
  178.     tmp.copyTo(q2);  
  179. }  
  180. /* 
  181. template < typename type> 
  182. cv::Mat fouriertransFull(const cv::Mat & in) 
  183. { 
  184.     return fftd(in); 
  185.  
  186.     cv::Mat planes[] = {cv::Mat_<type > (in), cv::Mat_<type>::zeros(in.size())}; 
  187.     cv::Mat t; 
  188.     assert(planes[0].depth() == planes[1].depth()); 
  189.     assert(planes[0].size == planes[1].size); 
  190.     cv::merge(planes, 2, t); 
  191.     cv::dft(t, t); 
  192.  
  193.     //cv::normalize(a, a, 0, 1, CV_MINMAX); 
  194.     //cv::normalize(t, t, 0, 1, CV_MINMAX); 
  195.  
  196.     // cv::imshow("a",real(a)); 
  197.     //  cv::imshow("b",real(t)); 
  198.     // cv::waitKey(0); 
  199.  
  200.     return t; 
  201. }*/  
  202.   
  203. // 做对数变换初始化  
  204. void normalizedLogTransform(cv::Mat &img)  
  205. {  
  206.     img = cv::abs(img);  
  207.     img += cv::Scalar::all(1);  
  208.     cv::log(img, img);  
  209.     // cv::normalize(img, img, 0, 1, CV_MINMAX);  
  210. }  
  211.   
  212. }  

recttools.hpp

  1. #pragma once  
  2.   
  3. //#include <cv.h>  
  4. #include <math.h>  
  5.   
  6. #ifndef _OPENCV_RECTTOOLS_HPP_  
  7. #define _OPENCV_RECTTOOLS_HPP_  
  8. #endif  
  9.   
  10. namespace RectTools  
  11. {  
  12.   
  13. // 取中心坐标  
  14. template <typename t>  
  15. inline cv::Vec<t, 2 > center(const cv::Rect_<t> &rect)  
  16. {  
  17.     return cv::Vec<t, 2 > (rect.x + rect.width / (t) 2, rect.y + rect.height / (t) 2);  
  18. }  
  19.   
  20. // 取右边界  
  21. template <typename t>  
  22. inline t x2(const cv::Rect_<t> &rect)  
  23. {  
  24.     return rect.x + rect.width;  
  25. }  
  26.   
  27. // 取下边界  
  28. template <typename t>  
  29. inline t y2(const cv::Rect_<t> &rect)  
  30. {  
  31.     return rect.y + rect.height;  
  32. }  
  33.   
  34. // 按scalex重新定义框的大小  
  35. template <typename t>  
  36. inline void resize(cv::Rect_<t> &rect, float scalex, float scaley = 0)  
  37. {  
  38.     if (!scaley)scaley = scalex;  
  39.     rect.x -= rect.width * (scalex - 1.f) / 2.f;  
  40.     rect.width *= scalex;  
  41.   
  42.     rect.y -= rect.height * (scaley - 1.f) / 2.f;  
  43.     rect.height *= scaley;  
  44.   
  45. }  
  46.   
  47. // 把rect限制在limit的范围内  
  48. template <typename t>  
  49. inline void limit(cv::Rect_<t> &rect, cv::Rect_<t> limit)  
  50. {  
  51.     if (rect.x + rect.width > limit.x + limit.width)rect.width = (limit.x + limit.width - rect.x);  
  52.     if (rect.y + rect.height > limit.y + limit.height)rect.height = (limit.y + limit.height - rect.y);  
  53.     if (rect.x < limit.x)  
  54.     {  
  55.         rect.width -= (limit.x - rect.x);  
  56.         rect.x = limit.x;  
  57.     }  
  58.     if (rect.y < limit.y)  
  59.     {  
  60.         rect.height -= (limit.y - rect.y);  
  61.         rect.y = limit.y;  
  62.     }  
  63.     if(rect.width<0)rect.width=0;  
  64.     if(rect.height<0)rect.height=0;  
  65. }  
  66.   
  67. // 接口重定义  
  68. template <typename t>  
  69. inline void limit(cv::Rect_<t> &rect, t width, t height, t x = 0, t y = 0)  
  70. {  
  71.     limit(rect, cv::Rect_<t > (x, y, width, height));  
  72. }  
  73.   
  74. // 取超出来的边界  
  75. template <typename t>  
  76. inline cv::Rect getBorder(const cv::Rect_<t > &original, cv::Rect_<t > & limited)  
  77. {  
  78.     cv::Rect_<t > res;  
  79.     res.x = limited.x - original.x;  
  80.     res.y = limited.y - original.y;  
  81.     res.width = x2(original) - x2(limited);  
  82.     res.height = y2(original) - y2(limited);  
  83.     assert(res.x >= 0 && res.y >= 0 && res.width >= 0 && res.height >= 0);  
  84.     return res;  
  85. }  
  86.   
  87. // 取窗口大小  
  88. inline cv::Mat subwindow(const cv::Mat &in, const cv::Rect & window, int borderType = cv::BORDER_CONSTANT)  
  89. {  
  90.     cv::Rect cutWindow = window;  
  91.     RectTools::limit(cutWindow, in.cols, in.rows);  
  92.     if (cutWindow.height <= 0 || cutWindow.width <= 0)assert(0); //return cv::Mat(window.height,window.width,in.type(),0) ;  
  93.     cv::Rect border = RectTools::getBorder(window, cutWindow);  
  94.     cv::Mat res = in(cutWindow);  
  95.   
  96.     if (border != cv::Rect(0, 0, 0, 0))  
  97.     {  
  98.         // 使用Opencv来复制图像并填充边界  
  99.         cv::copyMakeBorder(res, res, border.y, border.height, border.x, border.width, borderType);  
  100.     }  
  101.     return res;  
  102. }  
  103.   
  104. // 获取灰度图像并将像素灰度转换成0-1之间的小数  
  105. inline cv::Mat getGrayImage(cv::Mat img)  
  106. {  
  107.     cv::cvtColor(img, img, CV_BGR2GRAY);  
  108.     img.convertTo(img, CV_32F, 1 / 255.f);  
  109.     return img;  
  110. }  
  111.   
  112. }  


runtracker.hpp:跟踪主程序

  1. #include <iostream>  
  2. #include <fstream>  
  3. #include <sstream>  
  4. #include <algorithm>  
  5.   
  6. #include <opencv2/core/core.hpp>  
  7. #include <opencv2/highgui/highgui.hpp>  
  8.   
  9. #include "kcftracker.hpp"  
  10.   
  11. #include <dirent.h>  
  12.   
  13. #include <sys/time.h>  
  14.   
  15. using namespace std;  
  16. using namespace cv;  
  17.   
  18. int main(int argc, char* argv[]){  
  19.   struct timeval tv, tz,tv0, tz0;  
  20.   
  21.     if (argc > 5) return -1;            // 输入大于5个参数  
  22.   
  23.     bool HOG = true;                    // 是否使用hog特征  
  24.     bool FIXEDWINDOW = false;           // 是否使用修正窗口  
  25.     bool MULTISCALE = true;             // 是否使用多尺度  
  26.     bool SILENT = true;                 // 是否不做显示  
  27.     bool LAB = false;                   // 是否使用LAB颜色  
  28.   
  29.     for(int i = 0; i < argc; i++){  
  30.         if ( strcmp (argv[i], "hog") == 0 )  
  31.             HOG = true;  
  32.         if ( strcmp (argv[i], "fixed_window") == 0 )  
  33.             FIXEDWINDOW = true;  
  34.         if ( strcmp (argv[i], "singlescale") == 0 )  
  35.             MULTISCALE = false;  
  36.         if ( strcmp (argv[i], "show") == 0 )  
  37.             SILENT = false;  
  38.         if ( strcmp (argv[i], "lab") == 0 ){  
  39.             LAB = true;  
  40.             HOG = true;  
  41.         }  
  42.         if ( strcmp (argv[i], "gray") == 0 )  
  43.             HOG = false;  
  44.     }  
  45.   
  46.     // Create KCFTracker object  
  47.     // 创建KCF跟踪器  
  48.     KCFTracker tracker(HOG, FIXEDWINDOW, MULTISCALE, LAB);  
  49.   
  50.     // Frame readed  
  51.     // 当前帧  
  52.     Mat frame;  
  53.   
  54.     // Tracker results  
  55.     // 跟踪结果目标框  
  56.     Rect result;  
  57.   
  58.     // Path to list.txt  
  59.     // images.txt的路径,用于读取图像  
  60.     ifstream listFile;  
  61.     string fileName = "images.txt";  
  62.     listFile.open(fileName);  
  63.   
  64.     // Read groundtruth for the 1st frame  
  65.     // 读取第一帧的目标区域  
  66.     ifstream groundtruthFile;  
  67.     string groundtruth = "region.txt";  
  68.     groundtruthFile.open(groundtruth);  
  69.     string firstLine;  
  70.     getline(groundtruthFile, firstLine);  
  71.     groundtruthFile.close();  
  72.   
  73.     istringstream ss(firstLine);  
  74.   
  75.     // Read groundtruth like a dumb  
  76.     // 从给定的第一帧目标框读入四个顶点的坐标  
  77.     float x1, y1, x2, y2, x3, y3, x4, y4;  
  78.     char ch;  
  79.     ss >> x1;  
  80.     ss >> ch;  
  81.     ss >> y1;  
  82.     ss >> ch;  
  83.     ss >> x2;  
  84.     ss >> ch;  
  85.     ss >> y2;  
  86.     ss >> ch;  
  87.     ss >> x3;  
  88.     ss >> ch;  
  89.     ss >> y3;  
  90.     ss >> ch;  
  91.     ss >> x4;  
  92.     ss >> ch;  
  93.     ss >> y4;  
  94.   
  95.   
  96.     // Using min and max of X and Y for groundtruth rectangle  
  97.     // 使用四个顶点计算出目标框  
  98.     float xMin =  min(x1, min(x2, min(x3, x4)));  
  99.     float yMin =  min(y1, min(y2, min(y3, y4)));  
  100.     float width = max(x1, max(x2, max(x3, x4))) - xMin;  
  101.     float height = max(y1, max(y2, max(y3, y4))) - yMin;  
  102.   
  103.   
  104.     // Read Images  
  105.     // 读图像  
  106.     ifstream listFramesFile;  
  107.     string listFrames = "images.txt";  
  108.     listFramesFile.open(listFrames);  
  109.     string frameName;  
  110.   
  111.   
  112.     // Write Results  
  113.     // 将结果写入output.txt  
  114.     ofstream resultsFile;  
  115.     string resultsPath = "output.txt";  
  116.     resultsFile.open(resultsPath);  
  117.   
  118.   
  119.     // Frame counter  
  120.     // 帧号计数  
  121.     int nFrames = 0;  
  122.     char name_write[15] = {};  
  123.   
  124.     while ( getline(listFramesFile, frameName) ){  
  125.         frameName = frameName;  
  126.   
  127.         // Read each frame from the list  
  128.         // 读取列表上面的帧  
  129.         frame = imread(frameName, CV_LOAD_IMAGE_COLOR);  
  130.   
  131.         // First frame, give the groundtruth to the tracker  
  132.         // 使用第一帧和目标框来初始化跟踪器  
  133.         if (nFrames == 0) {  
  134.             tracker.init( Rect(xMin, yMin, width, height), frame );  
  135.             rectangle( frame, Point( xMin, yMin ), Point( xMin+width, yMin+height), Scalar( 0, 255, 255 ), 1, 8 );  
  136.             resultsFile << xMin << "," << yMin << "," << width << "," << height << endl;  
  137.         }  
  138.         // Update  
  139.         // 更新当前帧的结果  
  140.         else{  
  141.             result = tracker.update(frame);  
  142.             rectangle( frame, Point( result.x, result.y ), Point( result.x+result.width, result.y+result.height), Scalar( 0, 255, 255 ), 1, 8 );  
  143.             resultsFile << result.x << "," << result.y << "," << result.width << "," << result.height << endl;  
  144.         }  
  145.         nFrames++;  
  146.   
  147.         // 显示并保存  
  148.         if (!SILENT){  
  149.             imshow("Image", frame);  
  150.             waitKey(1);  
  151.             sprintf(name_write, "%04d.jpg", nFrames);  
  152.             imwrite(name_write, frame);  
  153.         }  
  154.     }  
  155.     // 关闭文件  
  156.     resultsFile.close();  
  157.   
  158.     listFile.close();  
  159.   
  160. }
  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
## 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.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值