Compressive Tracking——CT跟踪

 

感谢香港理工大学的Kaihua Zhang,这是他即将在ECCV 2012上出现的paper:Real-time Compressive Tracking。 这里是他的介绍:

一种简单高效地基于压缩感知的跟踪算法。首先利用符合压缩感知RIP条件的随机感知矩对多尺度图像特征进行降维,然后在降维后的特征上采用简单的朴素贝叶斯分类器进行分类。该跟踪算法非常简单,但是实验结果很鲁棒,速度大概能到达40帧/秒。具体原理分析可参照相关文章。

链接

免积分下载代码:http://download.csdn.net/detail/sangni007/5297374

1.Description: compute Haar features    (templates)

  1. void CompressiveTracker::HaarFeature(Rect& _objectBox, int _numFeature)  

在rect内取_numFeature维特征,(rect的宽高与_objectBox一样,与_objectBox.x _objectBox.y无关)
每一维Feature都用若干Rect表示,存在vector<vector<Rect>> feature (_numFeature, vector<Rect>())中,

相应权重 vector<vector<float>>featuresWeight(_numFeature, vector<float>())

 

2.Description: compute the coordinate of positive and negative sample image templates

  1. void CompressiveTracker::sampleRect(Mat& _image, Rect& _objectBox, float _rInner,   
  2.     float _rOuter, int _maxSampleNum, vector<Rect>& _sampleBox)  

随机洒出若干Rect,记录坐标Rect(x,y)

保证sampleRect的(x,y)到_objectBox的(x,y)的dist满足:_rOuter*_rOuter<dist<_rInner*_rInner

取样本:1:正:dist小;2:负:dist大:

存入_sampleBox

  1. void CompressiveTracker::sampleRect(Mat& _image, Rect& _objectBox, float _srw, vector<Rect>& _sampleBox)  

这个sampleRect的重载函数是用来,预测位置的

只要满足:dist<_rInner*_rInner

初始化第一帧不运行这个sampleRect的重载函数,只在跟踪时,首先运行它再更新正负样本函数;

 

3.Compute the features of samples

  1. void CompressiveTracker::getFeatureValue(Mat& _imageIntegral, vector<Rect>& _sampleBox, Mat& _sampleFeatureValue)  

计算相应Rect的积分图像的Sum值,存入Mat& _sampleFeatureValue(即特征值)

 

4.// Update the mean and variance of the gaussian classifier

  1. void CompressiveTracker::classifierUpdate(Mat& _sampleFeatureValue, vector<float>& _mu, vector<float>& _sigma, float _learnRate)  

计算每个上一步积分矩阵Mat& _sampleFeatureValue中每一SampleBox的期望和标准差
并Update(具体计算采用文章的公式[6])

 

5.// Compute the ratio classifier

  1. void CompressiveTracker::radioClassifier(vector<float>& _muPos, vector<float>& _sigmaPos, vector<float>& _muNeg, vector<float>& _sigmaNeg, Mat& _sampleFeatureValue, float& _radioMax, int& _radioMaxIndex)  

利用朴素贝叶斯分类(gaussian model)文章公式[4]

计算所有sample的贝叶斯值,用radioMax存储最大值,即为预测位置

 

Discussion

这篇文章最成功的地方在于简单高效,绝对可以达到实时跟踪的效果,之前实验的粒子滤波就显得太慢了;但是有很多问题需要改进。(个人观点和网友总结,欢迎拍砖~)

1.尺度问题,只能对单尺度操作,当对象远离时跟踪框依然大小不变;

2.关于压缩感知,可以改进,比如选择features pool 像随机森林一样选择最优特征;

3.偏向当前新样本,所以很容易就遗忘以前学习过的样本,一旦偏离,会越偏越远;

4.我也是刚研究tracking by detection不久,拜读了compressive tracking,感觉很有新意,用这么简洁的方法就能实现较好的效果,这篇论文的实验部分很像mil tracking,mil的弱分类器也是假设使用高斯分布,但是我实验的结果是 haar like 特征并不是很好的服从高斯分布,尤其是negative sample,所以在物体的表征变化很大的时候,这种representation不能很好的捕捉到,另外里面有个学习参数 lambda,这个参数的设置也是一个经验值,据我的经验,一般是偏向当前新样本,所以很容易就遗忘以前学习过的样本,TLD的随机森林fern是记录正负样本个数来计算posterior,这种方式在long time tracking比这个要好,另外TLD在每个细节上做得很好,它的更新模型也是有动态系统的理论支持。以上是个人拙见,希望能多交流。——老熊

5.如果在一些跟踪算法上面加些trick,也是可以做 long time tracking的。TLD 的trick就是用了第一帧的信息,其实这个信息很多时候是不太好的。并且这种trick多年前就有人用过了,不是TLD新创的。另外 TLD 的PAMI文章没有说这个trick,CVPR10文章说了。CT这个方法简单,它的侧重点不是说拼什么跟踪效果,主要是在理论方面说明一下问题——zhkhua

  1. //---------------------------------------------------  
  2. class CompressiveTracker  
  3. {  
  4. public:  
  5.     CompressiveTracker(void);  
  6.     ~CompressiveTracker(void);  
  7.   
  8. private:  
  9.     int featureMinNumRect;  
  10.     int featureMaxNumRect;  
  11.     int featureNum;  
  12.     vector<vector<Rect>> features;  
  13.     vector<vector<float>> featuresWeight;  
  14.     int rOuterPositive;  
  15.     vector<Rect> samplePositiveBox;  
  16.     vector<Rect> sampleNegativeBox;  
  17.     int rSearchWindow;  
  18.     Mat imageIntegral;  
  19.     Mat samplePositiveFeatureValue;  
  20.     Mat sampleNegativeFeatureValue;  
  21.     vector<float> muPositive;  
  22.     vector<float> sigmaPositive;  
  23.     vector<float> muNegative;  
  24.     vector<float> sigmaNegative;  
  25.     float learnRate;  
  26.     vector<Rect> detectBox;  
  27.     Mat detectFeatureValue;  
  28.     RNG rng;  
  29.   
  30. private:  
  31.     void HaarFeature(Rect& _objectBox, int _numFeature);  
  32.     void sampleRect(Mat& _image, Rect& _objectBox, float _rInner, float _rOuter, int _maxSampleNum, vector<Rect>& _sampleBox);  
  33.     void sampleRect(Mat& _image, Rect& _objectBox, float _srw, vector<Rect>& _sampleBox);  
  34.     void getFeatureValue(Mat& _imageIntegral, vector<Rect>& _sampleBox, Mat& _sampleFeatureValue);  
  35.     void classifierUpdate(Mat& _sampleFeatureValue, vector<float>& _mu, vector<float>& _sigma, float _learnRate);  
  36.     void radioClassifier(vector<float>& _muPos, vector<float>& _sigmaPos, vector<float>& _muNeg, vector<float>& _sigmaNeg,  
  37.                         Mat& _sampleFeatureValue, float& _radioMax, int& _radioMaxIndex);  
  38. public:  
  39.     void processFrame(Mat& _frame, Rect& _objectBox);  
  40.     void init(Mat& _frame, Rect& _objectBox);  
  41. };  

 

 

  1. #include "CompressiveTracker.h"  
  2. #include <math.h>  
  3. #include <iostream>  
  4. using namespace cv;  
  5. using namespace std;  
  6.   
  7. //------------------------------------------------  
  8. CompressiveTracker::CompressiveTracker(void)  
  9. {  
  10.     featureMinNumRect = 2;  
  11.     featureMaxNumRect = 4;  // number of rectangle from 2 to 4  
  12.     featureNum = 50;    // number of all weaker classifiers, i.e,feature pool  
  13.     rOuterPositive = 4; // radical scope of positive samples  
  14.     rSearchWindow = 25; // size of search window  
  15.     muPositive = vector<float>(featureNum, 0.0f);  
  16.     muNegative = vector<float>(featureNum, 0.0f);  
  17.     sigmaPositive = vector<float>(featureNum, 1.0f);  
  18.     sigmaNegative = vector<float>(featureNum, 1.0f);  
  19.     learnRate = 0.85f;  // Learning rate parameter  
  20. }  
  21.   
  22. CompressiveTracker::~CompressiveTracker(void)  
  23. {  
  24. }  
  25.   
  26.   
  27. void CompressiveTracker::HaarFeature(Rect& _objectBox, int _numFeature)  
  28. /*Description: compute Haar features 
  29.   Arguments: 
  30.   -_objectBox: [x y width height] object rectangle 
  31.   -_numFeature: total number of features.The default is 50. 
  32. */  
  33. {  
  34.     features = vector<vector<Rect>>(_numFeature, vector<Rect>());  
  35.     featuresWeight = vector<vector<float>>(_numFeature, vector<float>());  
  36.       
  37.     int numRect;  
  38.     Rect rectTemp;  
  39.     float weightTemp;  
  40.         
  41.     for (int i=0; i<_numFeature; i++)  
  42.     {  
  43.         //每一个特征生成一个平均分布的随机数, 这个特征用几个Rect表示;  
  44.         numRect = cvFloor(rng.uniform((double)featureMinNumRect, (double)featureMaxNumRect));  
  45.           
  46.         for (int j=0; j<numRect; j++)  
  47.         {  
  48.             //在Rcet(x,y,w,h)内画随机rectTemp,事实上,只用到了_objectBox的w和h,原则上在rect(0,0,w,h)内均匀分布;  
  49.             rectTemp.x = cvFloor(rng.uniform(0.0, (double)(_objectBox.width - 3)));  
  50.             rectTemp.y = cvFloor(rng.uniform(0.0, (double)(_objectBox.height - 3)));  
  51.             rectTemp.width = cvCeil(rng.uniform(0.0, (double)(_objectBox.width - rectTemp.x - 2)));  
  52.             rectTemp.height = cvCeil(rng.uniform(0.0, (double)(_objectBox.height - rectTemp.y - 2)));  
  53.             features[i].push_back(rectTemp);  
  54.   
  55.             weightTemp = (float)pow(-1.0, cvFloor(rng.uniform(0.0, 2.0))) / sqrt(float(numRect));  
  56.             featuresWeight[i].push_back(weightTemp);  
  57.              
  58.         }  
  59.     }  
  60. }  
  61.   
  62.   
  63. void CompressiveTracker::sampleRect(Mat& _image, Rect& _objectBox, float _rInner,   
  64.                                                             float _rOuter, int _maxSampleNum, vector<Rect>& _sampleBox)  
  65. /* Description: compute the coordinate of positive and negative sample image templates 
  66.    Arguments: 
  67.    -_image:        processing frame 
  68.    -_objectBox:    recent object position  
  69.    -_rInner:       inner sampling radius 
  70.    -_rOuter:       Outer sampling radius 
  71.    -_maxSampleNum: maximal number of sampled images 
  72.    -_sampleBox:    Storing the rectangle coordinates of the sampled images. 
  73. */  
  74. {  
  75.     int rowsz = _image.rows - _objectBox.height - 1;  
  76.     int colsz = _image.cols - _objectBox.width - 1;  
  77.     float inradsq = _rInner*_rInner;//4*4  
  78.     float outradsq = _rOuter*_rOuter;//0*0  
  79.   
  80.       
  81.     int dist;  
  82.   
  83.     int minrow = max(0,(int)_objectBox.y-(int)_rInner);//起始位置最小坐标处;  
  84.     int maxrow = min((int)rowsz-1,(int)_objectBox.y+(int)_rInner);//起始位置最大坐标处;  
  85.     int mincol = max(0,(int)_objectBox.x-(int)_rInner);  
  86.     int maxcol = min((int)colsz-1,(int)_objectBox.x+(int)_rInner);  
  87.       
  88.       
  89.       
  90.     int i = 0;  
  91.   
  92.     float prob = ((float)(_maxSampleNum))/(maxrow-minrow+1)/(maxcol-mincol+1);  
  93.   
  94.     int r;  
  95.     int c;  
  96.       
  97.     _sampleBox.clear();//important  
  98.     Rect rec(0,0,0,0);  
  99.   
  100.     for( r=minrow; r<=(int)maxrow; r++ )  
  101.         for( c=mincol; c<=(int)maxcol; c++ ){  
  102.             //保证sampleRect的(x,y)到_objectBox的(x,y)的dist满足:_rOuter*_rOuter<dist<_rInner*_rInner  
  103.             dist = (_objectBox.y-r)*(_objectBox.y-r) + (_objectBox.x-c)*(_objectBox.x-c);  
  104.               
  105.             if( rng.uniform(0.,1.)<prob && dist < inradsq && dist >= outradsq ){  
  106.   
  107.                 rec.x = c;  
  108.                 rec.y = r;  
  109.                 rec.width = _objectBox.width;  
  110.                 rec.height= _objectBox.height;  
  111.                   
  112.                 _sampleBox.push_back(rec);                
  113.                   
  114.                 i++;  
  115.             }  
  116.         }  
  117.       
  118.         _sampleBox.resize(i);  
  119.           
  120. }  
  121.   
  122. void CompressiveTracker::sampleRect(Mat& _image, Rect& _objectBox, float _srw, vector<Rect>& _sampleBox)  
  123. /* Description: Compute the coordinate of samples when detecting the object.*/  
  124. {  
  125.     int rowsz = _image.rows - _objectBox.height - 1;  
  126.     int colsz = _image.cols - _objectBox.width - 1;  
  127.     float inradsq = _srw*_srw;    
  128.       
  129.   
  130.     int dist;  
  131.   
  132.     int minrow = max(0,(int)_objectBox.y-(int)_srw);  
  133.     int maxrow = min((int)rowsz-1,(int)_objectBox.y+(int)_srw);  
  134.     int mincol = max(0,(int)_objectBox.x-(int)_srw);  
  135.     int maxcol = min((int)colsz-1,(int)_objectBox.x+(int)_srw);  
  136.   
  137.     int i = 0;  
  138.   
  139.     int r;  
  140.     int c;  
  141.   
  142.     Rect rec(0,0,0,0);  
  143.     _sampleBox.clear();//important  
  144.   
  145.     for( r=minrow; r<=(int)maxrow; r++ )  
  146.         for( c=mincol; c<=(int)maxcol; c++ ){  
  147.             dist = (_objectBox.y-r)*(_objectBox.y-r) + (_objectBox.x-c)*(_objectBox.x-c);  
  148.   
  149.             if( dist < inradsq ){  
  150.   
  151.                 rec.x = c;  
  152.                 rec.y = r;  
  153.                 rec.width = _objectBox.width;  
  154.                 rec.height= _objectBox.height;  
  155.   
  156.                 _sampleBox.push_back(rec);                
  157.   
  158.                 i++;  
  159.             }  
  160.         }  
  161.       
  162.         _sampleBox.resize(i);  
  163.   
  164. }  
  165. // Compute the features of samples  
  166. void CompressiveTracker::getFeatureValue(Mat& _imageIntegral, vector<Rect>& _sampleBox, Mat& _sampleFeatureValue)  
  167. {  
  168.     int sampleBoxSize = _sampleBox.size();  
  169.     _sampleFeatureValue.create(featureNum, sampleBoxSize, CV_32F);  
  170.     float tempValue;  
  171.     int xMin;  
  172.     int xMax;  
  173.     int yMin;  
  174.     int yMax;  
  175.   
  176.     for (int i=0; i<featureNum; i++)  
  177.     {  
  178.         for (int j=0; j<sampleBoxSize; j++)  
  179.         {  
  180.             tempValue = 0.0f;  
  181.             for (size_t k=0; k<features[i].size(); k++)  
  182.             {  
  183.                 xMin = _sampleBox[j].x + features[i][k].x;  
  184.                 xMax = _sampleBox[j].x + features[i][k].x + features[i][k].width;  
  185.                 yMin = _sampleBox[j].y + features[i][k].y;  
  186.                 yMax = _sampleBox[j].y + features[i][k].y + features[i][k].height;  
  187.                 tempValue += featuresWeight[i][k] *   
  188.                     (_imageIntegral.at<float>(yMin, xMin) +      //计算指定区域的积分图像的sum值;  
  189.                     _imageIntegral.at<float>(yMax, xMax) -  
  190.                     _imageIntegral.at<float>(yMin, xMax) -  
  191.                     _imageIntegral.at<float>(yMax, xMin));  
  192.             }  
  193.             _sampleFeatureValue.at<float>(i,j) = tempValue; //计算指定区域的积分图像的sum值,作为特征;  
  194.         }  
  195.     }  
  196. }  
  197.   
  198. // Update the mean and variance of the gaussian classifier  
  199. void CompressiveTracker::classifierUpdate(Mat& _sampleFeatureValue, vector<float>& _mu, vector<float>& _sigma, float _learnRate)  
  200. {  
  201.     Scalar muTemp;  
  202.     Scalar sigmaTemp;  
  203.       
  204.     for (int i=0; i<featureNum; i++)  
  205.     {  
  206.         meanStdDev(_sampleFeatureValue.row(i), muTemp, sigmaTemp);  
  207.          
  208.         _sigma[i] = (float)sqrt( _learnRate*_sigma[i]*_sigma[i] + (1.0f-_learnRate)*sigmaTemp.val[0]*sigmaTemp.val[0]   
  209.         + _learnRate*(1.0f-_learnRate)*(_mu[i]-muTemp.val[0])*(_mu[i]-muTemp.val[0]));  // equation 6 in paper  
  210.   
  211.         _mu[i] = _mu[i]*_learnRate + (1.0f-_learnRate)*muTemp.val[0];   // equation 6 in paper  
  212.     }  
  213. }  
  214.   
  215. // Compute the ratio classifier   
  216. void CompressiveTracker::radioClassifier(vector<float>& _muPos, vector<float>& _sigmaPos, vector<float>& _muNeg, vector<float>& _sigmaNeg,  
  217.                                          Mat& _sampleFeatureValue, float& _radioMax, int& _radioMaxIndex)  
  218. {  
  219.     float sumRadio;  
  220.     _radioMax = -FLT_MAX;  
  221.     _radioMaxIndex = 0;  
  222.     float pPos;  
  223.     float pNeg;  
  224.     int sampleBoxNum = _sampleFeatureValue.cols;  
  225.   
  226.     for (int j=0; j<sampleBoxNum; j++)  
  227.     {  
  228.         sumRadio = 0.0f;  
  229.         for (int i=0; i<featureNum; i++)  
  230.         {  
  231.             pPos = exp( (_sampleFeatureValue.at<float>(i,j)-_muPos[i])*(_sampleFeatureValue.at<float>(i,j)-_muPos[i]) / -(2.0f*_sigmaPos[i]*_sigmaPos[i]+1e-30) ) / (_sigmaPos[i]+1e-30);  
  232.             pNeg = exp( (_sampleFeatureValue.at<float>(i,j)-_muNeg[i])*(_sampleFeatureValue.at<float>(i,j)-_muNeg[i]) / -(2.0f*_sigmaNeg[i]*_sigmaNeg[i]+1e-30) ) / (_sigmaNeg[i]+1e-30);  
  233.             sumRadio += log(pPos+1e-30) - log(pNeg+1e-30);  // equation 4  
  234.         }  
  235.         if (_radioMax < sumRadio)  
  236.         {  
  237.             _radioMax = sumRadio;  
  238.             _radioMaxIndex = j;  
  239.         }  
  240.     }  
  241. }  
  242. void CompressiveTracker::init(Mat& _frame, Rect& _objectBox)  
  243. {  
  244.     // compute feature template  
  245.     HaarFeature(_objectBox, featureNum);  
  246.   
  247.     // compute sample templates  
  248.     sampleRect(_frame, _objectBox, rOuterPositive, 0, 1000000, samplePositiveBox);  
  249.     sampleRect(_frame, _objectBox, rSearchWindow*1.5, rOuterPositive+4.0, 100, sampleNegativeBox);  
  250.   
  251.     integral(_frame, imageIntegral, CV_32F);//计算积分图像;  
  252.   
  253.     getFeatureValue(imageIntegral, samplePositiveBox, samplePositiveFeatureValue);  
  254.     getFeatureValue(imageIntegral, sampleNegativeBox, sampleNegativeFeatureValue);  
  255.     classifierUpdate(samplePositiveFeatureValue, muPositive, sigmaPositive, learnRate);  
  256.     classifierUpdate(sampleNegativeFeatureValue, muNegative, sigmaNegative, learnRate);  
  257. }  
  258. void CompressiveTracker::processFrame(Mat& _frame, Rect& _objectBox)  
  259. {  
  260.     // predict  
  261.     sampleRect(_frame, _objectBox, rSearchWindow,detectBox);  
  262.     integral(_frame, imageIntegral, CV_32F);  
  263.     getFeatureValue(imageIntegral, detectBox, detectFeatureValue);  
  264.     int radioMaxIndex;  
  265.     float radioMax;  
  266.     radioClassifier(muPositive, sigmaPositive, muNegative, sigmaNegative, detectFeatureValue, radioMax, radioMaxIndex);  
  267.     _objectBox = detectBox[radioMaxIndex];  
  268.   
  269.     // update  
  270.     sampleRect(_frame, _objectBox, rOuterPositive, 0.0, 1000000, samplePositiveBox);  
  271.     sampleRect(_frame, _objectBox, rSearchWindow*1.5, rOuterPositive+4.0, 100, sampleNegativeBox);  
  272.       
  273.     getFeatureValue(imageIntegral, samplePositiveBox, samplePositiveFeatureValue);  
  274.     getFeatureValue(imageIntegral, sampleNegativeBox, sampleNegativeFeatureValue);  
  275.     classifierUpdate(samplePositiveFeatureValue, muPositive, sigmaPositive, learnRate);  
  276.     classifierUpdate(sampleNegativeFeatureValue, muNegative, sigmaNegative, learnRate);  
  277. }  


参考文献:

增强视觉:http://www.cvchina.info/2012/07/31/real-time-compressive-tracking/


©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页