压缩感知跟踪(二)

来源:互联网 发布:php获取p标签中的img 编辑:程序博客网 时间:2024/04/28 05:31

   上一篇博客我按matlab的执行顺序贴上了matlab版本的代码,这次准备在这里贴上CT的C++代码,希望可以对比学学。事实上我通过运行两个版本的代码,发现matlab比C++版本的代码要快,这个和TLD类似哦。

平台: VS2010 + OpenCV2.4.6

先上一些图,下面是论文中的图。







接着,下面是论文中公式:



         





下面是论文的算法流程



最后,我还是贴上C++代码吧,我注释了。

CompressiveTracker.h头文件,定义了CompressiveTracker类

/************************************************************************* File:CompressiveTracker.h* Brief: C++ demo for paper: Kaihua Zhang, Lei Zhang, Ming-Hsuan Yang,"Real-Time Compressive Tracking," ECCV 2012.* Version: 1.0* Author: Yang Xian* Email: yang_xian521@163.com* Date:2012/08/03* History:* Revised by Kaihua Zhang on 14/8/2012, 23/8/2012* Email: zhkhua@gmail.com* Homepage: http://www4.comp.polyu.edu.hk/~cskhzhang/* Project Website: http://www4.comp.polyu.edu.hk/~cslzhang/CT/CT.htm************************************************************************/#pragma once#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <vector>using std::vector;using namespace cv;//---------------------------------------------------// 压缩感知跟踪器类class CompressiveTracker{public:CompressiveTracker(void);~CompressiveTracker(void);private:int featureMinNumRect;int featureMaxNumRect;int featureNum;                 //特征数目,这里我们设定了50个特征vector<vector<Rect>> features;  //特征:[x,y,w,h]vector<vector<float>> featuresWeight; //特征的权重int rOuterPositive; //初始正样本采集半径vector<Rect> samplePositiveBox;  //正样本集vector<Rect> sampleNegativeBox;  //负样本集int rSearchWindow;  //搜索窗口Mat imageIntegral;  //积分图Mat samplePositiveFeatureValue; //正样本特征集Mat sampleNegativeFeatureValue; //负样本特征集vector<float> muPositive;    //正样本的均值vector<float> sigmaPositive; //负样本的标准差vector<float> muNegative;    //负样本的均值vector<float> sigmaNegative; //负样本的标准差float learnRate;  //学习率vector<Rect> detectBox;  //检测窗口 Mat detectFeatureValue;  //检测窗口的特征集合RNG rng;private://计算haar窗口(特征)void HaarFeature(Rect& _objectBox, int _numFeature);//采集样本void sampleRect(Mat& _image, Rect& _objectBox, float _rInner, float _rOuter, int _maxSampleNum, vector<Rect>& _sampleBox);//采集样本void sampleRect(Mat& _image, Rect& _objectBox, float _srw, vector<Rect>& _sampleBox);//计算采集到的样本的特征集合void getFeatureValue(Mat& _imageIntegral, vector<Rect>& _sampleBox, Mat& _sampleFeatureValue);//更新均值和标准差void classifierUpdate(Mat& _sampleFeatureValue, vector<float>& _mu, vector<float>& _sigma, float _learnRate);//计算比例,相对于相识度(匹配。。)void radioClassifier(vector<float>& _muPos, vector<float>& _sigmaPos, vector<float>& _muNeg, vector<float>& _sigmaNeg,Mat& _sampleFeatureValue, float& _radioMax, int& _radioMaxIndex);public://处理函数(除第一帧以外的视频帧(图像))void processFrame(Mat& _frame, Rect& _objectBox);//初始化函数(第一帧)void init(Mat& _frame, Rect& _objectBox);};

CompressiveTracker.cpp是CompressiveTracker类实现

#include "CompressiveTracker.h"#include <math.h>#include <iostream>using namespace cv;using namespace std;//------------------------------------------------//CT框架的构造函数,初始化相关参数CompressiveTracker::CompressiveTracker(void){//特征参数featureMinNumRect = 2;featureMaxNumRect = 4;// number of rectangle from 2 to 4//弱分类器个数,haar特征的个数为50featureNum = 50;// number of all weaker classifiers, i.e,feature pool//%正样本搜索半径,设置为4~8,目的是要采集正样本rOuterPositive = 4;// radical scope of positive samples//%新的一帧中的搜索窗口的半径,通常设置为15~35rSearchWindow = 25; // size of search window//均值,方差矢量容器//均值muPositive = vector<float>(featureNum, 0.0f);muNegative = vector<float>(featureNum, 0.0f);//方差sigmaPositive = vector<float>(featureNum, 1.0f);sigmaNegative = vector<float>(featureNum, 1.0f);//学习速率,通常设置为0.7~0.95learnRate = 0.85f;// Learning rate parameter}//析构函数CompressiveTracker::~CompressiveTracker(void){}// 计算haar特征void CompressiveTracker::HaarFeature(Rect& _objectBox, int _numFeature)/*Description: compute Haar features  Arguments:  -_objectBox: [x y width height] object rectangle  -_numFeature: total number of features.The default is 50.*/{//创建矢量容器//特征矢量容器features = vector<vector<Rect>>(_numFeature, vector<Rect>());//特征权重矢量容器featuresWeight = vector<vector<float>>(_numFeature, vector<float>());int numRect;Rect rectTemp;float weightTemp;    //for i=1:Mfor (int i=0; i<_numFeature; i++){//生成一个产生均匀分布的数[2,4]之间numRect = cvFloor(rng.uniform((double)featureMinNumRect, (double)featureMaxNumRect));for (int j=0; j<numRect; j++){rectTemp.x = cvFloor(rng.uniform(0.0, (double)(_objectBox.width - 3)));rectTemp.y = cvFloor(rng.uniform(0.0, (double)(_objectBox.height - 3)));rectTemp.width = cvCeil(rng.uniform(0.0, (double)(_objectBox.width - rectTemp.x - 2)));rectTemp.height = cvCeil(rng.uniform(0.0, (double)(_objectBox.height - rectTemp.y - 2)));//将[x,y,w,h]放入矢量容器features中features[i].push_back(rectTemp);weightTemp = (float)pow(-1.0, cvFloor(rng.uniform(0.0, 2.0))) / sqrt(float(numRect));//将权重放入矢量容器中featuresWeight[i].push_back(weightTemp);           }}}// 计算正负样本图像模板的坐标(取样本)void CompressiveTracker::sampleRect(Mat& _image, Rect& _objectBox, float _rInner, float _rOuter, int _maxSampleNum, vector<Rect>& _sampleBox)/* Description: compute the coordinate of positive and negative sample image templates   Arguments:   -_image:        processing frame   -_objectBox:    recent object position  [x y width height]    -_rInner:       inner sampling radius   -_rOuter:       Outer sampling radius   -_maxSampleNum: maximal number of sampled images 样本总数   返回值   -_sampleBox:    Storing the rectangle coordinates of the sampled images. 存储样本图像坐标[sx,sy,sw,sh]*/{int rowsz = _image.rows - _objectBox.height - 1; //行int colsz = _image.cols - _objectBox.width - 1;  //列float inradsq = _rInner*_rInner;float outradsq = _rOuter*_rOuter;  int dist;int minrow = max(0,(int)_objectBox.y-(int)_rInner);              //最小行int maxrow = min((int)rowsz-1,(int)_objectBox.y+(int)_rInner);   //最大行int mincol = max(0,(int)_objectBox.x-(int)_rInner);              //最小列int maxcol = min((int)colsz-1,(int)_objectBox.x+(int)_rInner);   //最大列    int i = 0;float prob = ((float)(_maxSampleNum))/(maxrow-minrow+1)/(maxcol-mincol+1);int r;int c;    //清空矢量容器,_sampleBox是返回值    _sampleBox.clear();//important    Rect rec(0,0,0,0);for( r=minrow; r<=(int)maxrow; r++ ) for( c=mincol; c<=(int)maxcol; c++ ){ //先列,后行dist = (_objectBox.y-r)*(_objectBox.y-r) + (_objectBox.x-c)*(_objectBox.x-c);if( rng.uniform(0.,1.)<prob && dist < inradsq && dist >= outradsq ){                rec.x = c; //xrec.y = r; //yrec.width = _objectBox.width;rec.height= _objectBox.height;//将满足条件的[x,y,w,h]保存到矢量先来_sampleBox                _sampleBox.push_back(rec);i++;}}_sampleBox.resize(i);}void CompressiveTracker::sampleRect(Mat& _image, Rect& _objectBox, float _srw, vector<Rect>& _sampleBox)/* Description: Compute the coordinate of samples when detecting the object.*/{int rowsz = _image.rows - _objectBox.height - 1;int colsz = _image.cols - _objectBox.width - 1;float inradsq = _srw*_srw;int dist;int minrow = max(0,(int)_objectBox.y-(int)_srw);int maxrow = min((int)rowsz-1,(int)_objectBox.y+(int)_srw);int mincol = max(0,(int)_objectBox.x-(int)_srw);int maxcol = min((int)colsz-1,(int)_objectBox.x+(int)_srw);int i = 0;int r;int c;Rect rec(0,0,0,0);    _sampleBox.clear();//importantfor( r=minrow; r<=(int)maxrow; r++ )for( c=mincol; c<=(int)maxcol; c++ ){dist = (_objectBox.y-r)*(_objectBox.y-r) + (_objectBox.x-c)*(_objectBox.x-c);if( dist < inradsq ){rec.x = c;rec.y = r;rec.width = _objectBox.width;rec.height= _objectBox.height;_sampleBox.push_back(rec);i++;}}_sampleBox.resize(i);}// Compute the features of samples// 计算样本的特征值void CompressiveTracker::getFeatureValue(Mat& _imageIntegral, vector<Rect>& _sampleBox, Mat& _sampleFeatureValue){//样本个数int sampleBoxSize = _sampleBox.size();//开辟一个空间,用来存放每个样本的特征值,特征个数为featureNum//一个样本用50个特征来表示_sampleFeatureValue.create(featureNum, sampleBoxSize, CV_32F);float tempValue;int xMin;int xMax;int yMin;int yMax;//对于每一个样本,计算他的每一个特征的特征值for (int i=0; i<featureNum; i++)  //每一个特征{for (int j=0; j<sampleBoxSize; j++) //每一个样本{ tempValue = 0.0f;for (size_t k=0; k<features[i].size(); k++){xMin = _sampleBox[j].x + features[i][k].x;                         //xxMax = _sampleBox[j].x + features[i][k].x + features[i][k].width;  //xyMin = _sampleBox[j].y + features[i][k].y;                         //yyMax = _sampleBox[j].y + features[i][k].y + features[i][k].height; //y//通过积分图像计算特征值。按特征值的权重进行累计得到样本的每个特征值tempValue += featuresWeight[i][k] * (_imageIntegral.at<float>(yMin, xMin) +_imageIntegral.at<float>(yMax, xMax) -_imageIntegral.at<float>(yMin, xMax) -_imageIntegral.at<float>(yMax, xMin));}_sampleFeatureValue.at<float>(i,j) = tempValue; //特征值}}}// Update the mean and variance of the gaussian classifiervoid CompressiveTracker::classifierUpdate(Mat& _sampleFeatureValue, vector<float>& _mu, vector<float>& _sigma, float _learnRate){Scalar muTemp;Scalar sigmaTemp;    //45个样本,每个样本50个特征for (int i=0; i<featureNum; i++) //对应每一个特征{//计算均值和标准差meanStdDev(_sampleFeatureValue.row(i), muTemp, sigmaTemp);    //更新:sigma = sqrt(beta*sigma1^2 + (1-beta)*sigma2^2)_sigma[i] = (float)sqrt( _learnRate*_sigma[i]*_sigma[i]+ (1.0f-_learnRate)*sigmaTemp.val[0]*sigmaTemp.val[0] + _learnRate*(1.0f-_learnRate)*(_mu[i]-muTemp.val[0])*(_mu[i]-muTemp.val[0]));// equation 6 in paper//更新均值_mu[i] = _mu[i]*_learnRate + (1.0f-_learnRate)*muTemp.val[0];// equation 6 in paper}}// Compute the ratio classifier // 这函数的返回值_radioMax,_radioMaxIndexvoid CompressiveTracker::radioClassifier(vector<float>& _muPos, vector<float>& _sigmaPos, vector<float>& _muNeg, vector<float>& _sigmaNeg, Mat& _sampleFeatureValue, float& _radioMax, int& _radioMaxIndex){float sumRadio;_radioMax = -FLT_MAX;_radioMaxIndex = 0;float pPos;float pNeg;//采集到的样本个数int sampleBoxNum = _sampleFeatureValue.cols;for (int j=0; j<sampleBoxNum; j++){sumRadio = 0.0f;for (int i=0; i<featureNum; i++){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);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);//公式4sumRadio += log(pPos+1e-30) - log(pNeg+1e-30);// equation 4}if (_radioMax < sumRadio){_radioMax = sumRadio;_radioMaxIndex = j;}}}//对第一帧进行一些初始化操作void CompressiveTracker::init(Mat& _frame, Rect& _objectBox){// compute feature template// 计算特征模板HaarFeature(_objectBox, featureNum);// compute sample templates// 计算样本模板//取正样本(采集正训练样本)sampleRect(_frame, _objectBox, rOuterPositive, 0, 1000000, samplePositiveBox);//取负样本(采集负训练样本)sampleRect(_frame, _objectBox, rSearchWindow*1.5, rOuterPositive+4.0, 100, sampleNegativeBox);//opencv的函数,求图像的积分图像,返回:imageIntegralintegral(_frame, imageIntegral, CV_32F);//正样本的特征集合samplePositiveFeatureValue,每个样本具有50个特征getFeatureValue(imageIntegral, samplePositiveBox, samplePositiveFeatureValue);//负样本的特征集合sampleNegativeFeatureValue,每个样本具有50个特征getFeatureValue(imageIntegral, sampleNegativeBox, sampleNegativeFeatureValue);//正样本,更新均值和标准差classifierUpdate(samplePositiveFeatureValue, muPositive, sigmaPositive, learnRate);//负样本,更新均值和标准差classifierUpdate(sampleNegativeFeatureValue, muNegative, sigmaNegative, learnRate);}void CompressiveTracker::processFrame(Mat& _frame, Rect& _objectBox){// predict// 对当前视频帧(图像)进行采样,采样的结果返回到detectBox中([x,y,w,h])sampleRect(_frame, _objectBox, rSearchWindow,detectBox);// 计算当前视频帧(图像)的积分图像integral(_frame, imageIntegral, CV_32F);// 计算采样的所有矩形框特征集合detectFeatureValuegetFeatureValue(imageIntegral, detectBox, detectFeatureValue);int radioMaxIndex;float radioMax;//这个函数相当于要判断目标在当前帧中的位置(几何角度:比较距离;概率角度:可能性大)//muPositive, sigmaPositive, muNegative, sigmaNegative,这些是前一帧(张)图像的均值和标准差//这函数的返回值_radioMax,_radioMaxIndexradioClassifier(muPositive, sigmaPositive, muNegative, sigmaNegative, detectFeatureValue, radioMax, radioMaxIndex);//选择检测窗口中的第_radioMaxIndex-1个窗口作为目标_objectBox = detectBox[radioMaxIndex];// update// 在当前帧中,采集正样本samplePositiveBoxsampleRect(_frame, _objectBox, rOuterPositive, 0.0, 1000000, samplePositiveBox);// 在当前帧中,采集负样本sampleNegativeBoxsampleRect(_frame, _objectBox, rSearchWindow*1.5, rOuterPositive+4.0, 100, sampleNegativeBox);// 由于上面已经计算得到了积分图像,所有就直接拿来使用// 计算正样本和负样本的特征集合samplePositiveFeatureValue,sampleNegativeFeatureValuegetFeatureValue(imageIntegral, samplePositiveBox, samplePositiveFeatureValue);getFeatureValue(imageIntegral, sampleNegativeBox, sampleNegativeFeatureValue);// 更新正负样本的均值和标准差classifierUpdate(samplePositiveFeatureValue, muPositive, sigmaPositive, learnRate);classifierUpdate(sampleNegativeFeatureValue, muNegative, sigmaNegative, learnRate);}

RunTracker.cpp是CT的主文件,用于运行跟踪器

/************************************************************************* File:RunTracker.cpp* Brief: C++ demo for paper: Kaihua Zhang, Lei Zhang, Ming-Hsuan Yang,"Real-Time Compressive Tracking," ECCV 2012.* Version: 1.0* Author: Yang Xian* Email: yang_xian521@163.com* Date:2012/08/03* History:* Revised by Kaihua Zhang on 14/8/2012, 23/8/2012* Email: zhkhua@gmail.com* Homepage: http://www4.comp.polyu.edu.hk/~cskhzhang/* Project Website: http://www4.comp.polyu.edu.hk/~cslzhang/CT/CT.htm************************************************************************/#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <iostream>#include <fstream>#include <sstream>#include <stdio.h>#include <string.h>#include "CompressiveTracker.h"#include <Windows.h>     /*这个是我添加上去的*/using namespace cv;using namespace std;//读取配置文件,实际上就是要读取初始帧的目标状态[x,y,w,h]void readConfig(char* configFileName, char* imgFilePath, Rect &box);/*  Description: read the tracking information from file "config.txt"    Arguments:-configFileName: config file name-ImgFilePath:    Path of the storing image sequences-box:            [x y width height] intial tracking positionHistory: Created by Kaihua Zhang on 15/8/2012*///读取图像数据void readImageSequenceFiles(char* ImgFilePath,vector <string> &imgNames);/*  Description: search the image names in the image sequences     Arguments:-ImgFilePath: path of the image sequence-imgNames:  vector that stores image nameHistory: Created by Kaihua Zhang on 15/8/2012*/int main(int argc, char * argv[]){char imgFilePath[100];    char  conf[100];strcpy(conf,"./config.txt");char tmpDirPath[MAX_PATH+1];Rect box; // [x y width height] tracking position//矢量容器vector <string> imgNames;    //读取配置文件初始帧的数据[x,y,w,h]readConfig(conf,imgFilePath,box);//读取图像数据readImageSequenceFiles(imgFilePath,imgNames);// CT framework// 这里把压缩感知跟踪写成了一个C++类CompressiveTracker ct;Mat frame;Mat grayImg;//格式化字符串sprintf(tmpDirPath, "%s/", imgFilePath);imgNames[0].insert(0,tmpDirPath);//读取第一张图像frame = imread(imgNames[0]);//转换为灰度图    cvtColor(frame, grayImg, CV_RGB2GRAY);    ct.init(grayImg, box);    char strFrame[20];    FILE* resultStream;//打开文件,用来写resultStream = fopen("TrackingResults.txt", "w");//格式化字符串fprintf (resultStream,"%i %i %i %i\n",(int)box.x,(int)box.y,(int)box.width,(int)box.height);/*******************************************************//*                       运行时                        *//*******************************************************///从第二张(帧)图像开始进行跟踪了for(int i = 1; i < imgNames.size()-1; i ++){//形成图像路径sprintf(tmpDirPath, "%s/", imgFilePath);        imgNames[i].insert(0,tmpDirPath);        //读取第i图像frame = imread(imgNames[i]);// get frame//转化为灰度图像cvtColor(frame, grayImg, CV_RGB2GRAY);ct.processFrame(grayImg, box);// Process framerectangle(frame, box, Scalar(200,0,0),2);// Draw rectanglefprintf (resultStream,"%i %i %i %i\n",(int)box.x,(int)box.y,(int)box.width,(int)box.height);sprintf(strFrame, "#%d ",i) ;putText(frame,strFrame,cvPoint(0,20),2,1,CV_RGB(25,200,25));imshow("CT", frame);// DisplaywaitKey(1);}fclose(resultStream);return 0;}//读取配置文件void readConfig(char* configFileName, char* imgFilePath, Rect &box){int x;int y;int w;int h;fstream f;char cstring[1000];int readS=0;//打开f.open(configFileName, fstream::in);char param1[200]; strcpy(param1,"");char param2[200]; strcpy(param2,"");char param3[200]; strcpy(param3,"");f.getline(cstring, sizeof(cstring));readS=sscanf (cstring, "%s %s %s", param1,param2, param3);strcpy(imgFilePath,param3);f.getline(cstring, sizeof(cstring)); f.getline(cstring, sizeof(cstring)); f.getline(cstring, sizeof(cstring));readS=sscanf (cstring, "%s %s %i %i %i %i", param1,param2, &x, &y, &w, &h);//初始帧目标状态box = Rect(x, y, w, h);}void readImageSequenceFiles(char* imgFilePath,vector <string> &imgNames){//清空矢量容器imgNames.clear();char tmpDirSpec[MAX_PATH+1];//格式化字符串sprintf (tmpDirSpec, "%s/*", imgFilePath);WIN32_FIND_DATA f;HANDLE h = FindFirstFile(tmpDirSpec , &f);if(h != INVALID_HANDLE_VALUE){FindNextFile(h, &f);//read ..FindNextFile(h, &f);//read .do{//将图像名称放进矢量容器imgNames中imgNames.push_back(f.cFileName);} while(FindNextFile(h, &f));}FindClose(h);}





0 0
原创粉丝点击