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

扫描二维码关注公众号,回复: 3449164 查看本文章
  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. }
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jacke121/article/details/54315050

猜你喜欢

转载自blog.csdn.net/zjc910997316/article/details/82903103
KCF