Real-Time Compressive Tracking论文代码详细注释

Real-Time Compressive Tracking

matlab源码在作者主页上可以下载:http://www4.comp.polyu.edu.hk/~cslzhang/CT/CT.htm
下面是全部matlab主要文件的代码及注释
注:为了注释在博客中方便地显示,将代码中%都替换为了//

Runtracker.m

// Demo for paper "Real-Time Compressive Tracking,"Kaihua Zhang, Lei Zhang, and Ming-Hsuan Yang
// To appear in European Conference on Computer Vision (ECCV 2012), Florence, Italy, October, 2012 
// Implemented by Kaihua Zhang, Dept.of Computing, HK PolyU.
// Email: zhkhua@gmail.com
// Date: 11/12/2011
// Revised by Kaihua Zhang, 15/12/2011
// Revised by Kaihua Zhang, 11/7/2012

// clc是清除命令行里面的内容,clear是清除那一堆存在内存里的数据的,close是关闭打开了的文件
//clear 清空工作区,clear all 清空工作区与全局变量,close 关闭当前窗口,close all 关闭所有窗口
clc;clear all;close all; 
//----------------------------------
// 设置随机数生成器状态为0,每次就可以产生相同的随机数,但是产生随机数后状态将改变
rand('state',0); 
//----------------------------------
// 如果要添加文件夹内所有子文件夹到路径的话,需使用genpath,pwd指当前工作路径
addpath('./data'); 
//----------------------------------
// load对象时txt格式时,以ASCII码格式读取,要求每一行数据个数一致
// initstate=[x y w h],x是图像水平方向,y是图像竖直方向,起点是图像的左上点。当图像变成矩阵进行处理时,索引方式和图像相反。
load init.txt;
initstate = init;//initial tracker
//----------------------------Set path
// 提取文件夹中格式为jpg的文件名
img_dir = dir('./data/*.png');
//---------------------------
// 图像读取结果是0~255的无符号整型数据
img = imread(img_dir(1).name);
// 先转换成浮点数据类型再惊进行计算。如果是三通道,仅使用第一个通道
img = double(img(:,:,1));
//----------------------------------------------------------------
trparams.init_negnumtrain = 50;//number of trained negative samples
trparams.init_postrainrad = 4.0;//radical scope of positive samples
trparams.initstate = initstate;// object position [x y width height]
trparams.srchwinsz = 20;// size of search window
// Sometimes, it affects the results.
//-------------------------
// classifier parameters,width和height表示目标框的宽和高
clfparams.width = trparams.initstate(3);
clfparams.height= trparams.initstate(4);
//-------------------------
// feature parameters
// number of rectangle from 2 to 4.
ftrparams.minNumRect = 2;
ftrparams.maxNumRect = 4;
//-------------------------
M = 50;// number of all weaker classifiers, i.e,feature pool
//-------------------------
posx.mu = zeros(M,1);// mean of positive features
negx.mu = zeros(M,1);
posx.sig= ones(M,1);// variance of positive features
negx.sig= ones(M,1);
//-------------------------Learning rate parameter
lRate = 0.85;
//-------------------------
//compute feature template,xywh属于图像坐标系
[ftr.px,ftr.py,ftr.pw,ftr.ph,ftr.pwt] = HaarFtr(clfparams,ftrparams,M);
//-------------------------
//compute sample templates,xywh属于图像坐标系
posx.sampleImage = sampleImg(img,initstate,trparams.init_postrainrad,0,100000);
negx.sampleImage = sampleImg(img,initstate,1.5*trparams.srchwinsz,4+trparams.init_postrainrad,50);
//-----------------------------------
//--------Feature extraction
iH = integral(img);//Compute integral image
posx.feature = getFtrVal(iH,posx.sampleImage,ftr);
negx.feature = getFtrVal(iH,negx.sampleImage,ftr);
//--------------------------------------------------
// update distribution parameters
[posx.mu,posx.sig,negx.mu,negx.sig] = classiferUpdate(posx,negx,posx.mu,posx.sig,negx.mu,negx.sig,lRate);
//-------------------------------------------------
num = length(img_dir);// number of frames
//--------------------------------------------------------
x = initstate(1);// x axis at the Top left corner
y = initstate(2);
w = initstate(3);// width of the rectangle
h = initstate(4);// height of the rectangle
//--------------------------------------------------------
for i = 2:num
    img = imread(img_dir(i).name);
    imgSr = img;// imgSr is used for showing tracking results.
    img = double(img(:,:,1));
    detectx.sampleImage = sampleImg(img,initstate,trparams.srchwinsz,0,100000);   
    iH = integral(img);//Compute integral image
    detectx.feature = getFtrVal(iH,detectx.sampleImage,ftr);
    //------------------------------------
    r = ratioClassifier(posx,negx,detectx);// compute the classifier for all samples
    clf = sum(r);// linearly combine the ratio classifiers in r to the final classifier
    //-------------------------------------
    [c,index] = max(clf);
    //--------------------------------
    x = detectx.sampleImage.sx(index);
    y = detectx.sampleImage.sy(index);
    w = detectx.sampleImage.sw(index);
    h = detectx.sampleImage.sh(index);
    initstate = [x y w h];
    //-------------------------------Show the tracking results
    imshow(imgSr);
    rectangle('Position',initstate,'LineWidth',4,'EdgeColor','r');
    hold on;
    text(5, 18, strcat('#',num2str(i)), 'Color','y', 'FontWeight','bold', 'FontSize',20);
    // gca返回当前图像坐标轴的句柄,set命令将坐标轴设置为0-1,0-1,这样显示的图像没有边框
    set(gca,'position',[0 0 1 1]);
    // 暂停执行后面命令,用于观察动态变化过程
    pause(0.00001); 
    hold off;
    //------------------------------Extract samples  
    posx.sampleImage = sampleImg(img,initstate,trparams.init_postrainrad,0,100000);
    negx.sampleImage = sampleImg(img,initstate,1.5*trparams.srchwinsz,4+trparams.init_postrainrad,trparams.init_negnumtrain);
    //--------------------------------------------------Update all the features 
    posx.feature = getFtrVal(iH,posx.sampleImage,ftr);
    negx.feature = getFtrVal(iH,negx.sampleImage,ftr);
    //--------------------------------------------------
    // update distribution parameters
    [posx.mu,posx.sig,negx.mu,negx.sig] = classiferUpdate(posx,negx,posx.mu,posx.sig,negx.mu,negx.sig,lRate);
end

HaarFtr.m

function [px,py,pw,ph,pwt] = HaarFtr(clfparams,ftrparams,M)

// $Description:
//    -Compute harr feature
// $Agruments
// Input;
//    -clfparams: classifier parameters
//    -clfparams.width: width of search window 
//    -clfparams.height:height of search window
//    -ftrparams: feature parameters
//    -ftrparams.minNumRect: minimal number of feature rectangles
//    -ftrparams.maxNumRect: maximal ....
//    -M: totle number of features
// Output:
//    -px: x coordinate, size: M x ftrparms.maxNumRect
//    -py: y ...
//    -pw: corresponding width,size:...
//    -ph: corresponding height,size:...
//    -pwt:corresponding weight,size:....Range:[-1 1]
// $ History $
//   - Created by Kaihua Zhang, on April 22th, 2011
//

width = clfparams.width;
height = clfparams.height;

// 对每个样本将会提取M个特征,每个特征模板包含随机数目的矩形框,矩形框由xywh确定位置
// wt是归一化系数,通过随机取正负号使得多个矩形框之间组合类型更加丰富。
px = zeros(M,ftrparams.maxNumRect);
py = zeros(M,ftrparams.maxNumRect);
pw = zeros(M,ftrparams.maxNumRect);
ph = zeros(M,ftrparams.maxNumRect);
pwt= zeros(M,ftrparams.maxNumRect);

for i=1:M
     // 对于每一个特征,选取在min与max之间随机数目的矩形框
     numrects = ftrparams.minNumRect + randi(ftrparams.maxNumRect-ftrparams.minNumRect)-1;
     for j = 1:numrects
        // xywh属于图像坐标系
        px(i,j) = randi(width-3);
        py(i,j) = randi(height-3);
        pw(i,j) = randi(width-px(i,j)-2);
        ph(i,j) = randi(height-py(i,j)-2);        

        pwt(i,j)= (-1)^(randi(2));
        pwt(i,j)=pwt(i,j)/sqrt(numrects);
     end      
end

// 画出M个特征对应的矩形框
// for i=1:M
//     figure();
//     rectangle('Position', [0 0 width height]);
//     for j = 1:ftrparams.maxNumRect
//         rectangle('Position', [px(i,j) py(i,j) pw(i,j)+1 ph(i,j)+1]);
//     end
// end

sampleImg.m

function samples = sampleImg(img,initstate,inrad,outrad,maxnum)
// $Description:
//    -Compute the coordinate of sample image templates
// $Agruments
// Input;
//    -img: inpute image
//    -initistate: [x y width height] object position 
//    -inrad: outside radius of region
//    -outrad: inside radius of region
//    -maxnum: maximal number of samples
// Output:
//    -samples.sx: x coordinate vector,[x1 x2 ...xn]
//    -samples.sy: y ...
//    -samples.sw: width ...
//    -samples.sh: height...
// $ History $
//   - Created by Kaihua Zhang, on April 22th, 2011
//   - Revised by Kaihua Zhang, on May 25th, 2011

// rand('state',0);//important

inrad = ceil(inrad); // 样本区域外边界
outrad= ceil(outrad); //样本区域内边界

[row,col] = size(img);
// xywh属于图像坐标系
x = initstate(1);
y = initstate(2);
w = initstate(3);
h = initstate(4);

// 样本矩形框顶点坐标在行和列的取值范围
rowsz = row - h - 1;
colsz = col - w - 1;

inradsq  = inrad^2; // 半径的平方(square)
outradsq = outrad^2;

// 在当前目标框顶点周围以inrad为半径的圆周内选取样本
minrow = max(1, y - inrad+1); 
maxrow = min(rowsz-1, y+inrad);
mincol = max(1, x-inrad+1);
maxcol = min(colsz-1, x+inrad);

// prob表示平均每个像素点上选择样本的数目,在后面将作为阈值来保证在候选区域内随机均匀选取要求数目的样本。
// 当选取正样本时,sampleImg函数最后一个参数值非常大,prob的值大于1,那么在半径范围内所有样本都是正样本。
// 而选取负样本的时候,prob的值再在0到1之间,那么将在半径范围内所有候选样本中随机筛选出要求数目的负样本
prob = maxnum/((maxrow-minrow+1)*(maxcol-mincol+1)); 
i = 1;
//--------------------------------------------------
//--------------------------------------------------
//命令meshgrid生成网格矩阵,r和c分别表示矩阵中所有点的横坐标和纵坐标
[r,c] = meshgrid(minrow:maxrow,mincol:maxcol); 
// 所有候选框与目标框间的距离的平方
dist  = (y-r).^2+(x-c).^2; 
// 对每个候选样本框生成一个随机数
rd = rand(size(r)); 

// >和<返回逻辑值0或1。&和&&的功能一样,但是&&不能适用于矩阵运算。
ind = (rd<prob)&(dist<inradsq)&(dist>=outradsq); 
//矩阵索引分为数组索引和逻辑索引。当使用逻辑索引时,逻辑矩阵元素必须是逻辑值,并且和要索引的矩阵大小一致
c = c(ind==1); 
r = r(ind==1);

// 将坐标值保存为行向量
samples.sx = c'; 
samples.sy = r';
samples.sw = w*ones(1,length(r(:)));
samples.sh = h*ones(1,length(r(:)));
//--------------------------------------------------
// for r = minrow:maxrow
//     for c = mincol:maxcol
//         dist = (y-r)^2 + (x-c)^2;         
//         if (rand<prob)&(dist<inradsq)&(dist>=outradsq)
//             samples.sx(i) = c;
//             samples.sy(i) = r;
//             samples.sw(i) = w;
//             samples.sh(i) = h;
//             i=i+1;
//         end
//     end    
// end

// 在图像中显示样本矩形框位置
imshow(img,[]);
rectangle('Position',initstate,'LineWidth',4,'EdgeColor','r');
set(gca,'position',[0 0 1 1]);
for i = i:numel(samples.sx)
    rectangle('Position', [samples.sx(i) samples.sy(i) samples.sw(i) samples.sh(i) ], 'LineWidth',1,'EdgeColor','y');
end

classiferUpdate.m

function [mu1,sig1,mu0,sig0] = classiferUpdate(posx,negx,mu1,sig1,mu0,sig0,lRate)
// $Description:
//    -Update the mean and variance of the gaussian classifier
// $Agruments
// Input;
//    -posx: positive sample set. We utilize the posx.feature
//    -negx: negative ....                   ... negx.feature
//    -mu1: mean of positive.feature M x 1 vector
//    -sig1:standard deviation of positive.feature M x 1 vector 
//    -mu0 : ...    negative
//    -sig0: ...    negative
//    -lRate: constant rate
// Output:
//    -mu1: updated mean of positive.feature
//    -sig1:...     standard deviation ....
//    -mu0: updated mean of negative.feature
//    -sig0:....    standard variance ...
// $ History $
//   - Created by Kaihua Zhang, on April 22th, 2011
//   - Changed by Kaihua Zhang, on May 18th, 2011
//--------------------------------------------------
// 分别求正负样本对于每个特征的均值和方差,每个特征值属于高斯分布
[prow,pcol] = size(posx.feature);
pmu = mean(posx.feature,2);
posmu = repmat(pmu,1,pcol);
sigm1 = mean((posx.feature-posmu).^2,2);

nmu = mean(negx.feature,2);
[nrow,ncol] = size(negx.feature);
negmu = repmat(nmu,1,ncol);
sigm0 = mean((negx.feature-negmu).^2,2);
//------------------------------------------Online MIL update method
// sig1= lRate*sig1+ (1-lRate)*sqrt(sigm1);
// mu1 = lRate*mu1 + (1-lRate)*pmu;
// 
// sig0= lRate*sig0+ (1-lRate)*sqrt(sigm0);
// mu0 = lRate*mu0 + (1-lRate)*nmu;
//---------------------------------------------
// Our update method,论文中有更新的公式
sig1= sqrt(lRate*sig1.^2+ (1-lRate)*sigm1+lRate*(1-lRate)*(mu1-pmu).^2);
mu1 = lRate*mu1 + (1-lRate)*pmu;

sig0= sqrt(lRate*sig0.^2+ (1-lRate)*sigm0+lRate*(1-lRate)*(mu0-nmu).^2);
mu0 = lRate*mu0 + (1-lRate)*nmu;

ratioClassifer.m

function r = ratioClassifier(posx,negx,samples)
// $Description:
//    -Compute the ratio classifier 
// $Agruments
// Input;
//    -posx: trained positive sample set. We utilize the posx.mu,posx.sig
//    -negx: trained negative ....                   ... negx.mu,negx.sig
//    -samples: tested samples. We utilize samples.feature
// Output:
//    -r: the computed classifier with respect to samples.feature
// $ History $
//   - Created by Kaihua Zhang, on April 22th, 2011

[row,col] = size(samples.feature);
mu1 = posx.mu;
sig1= posx.sig;
mu0 = negx.mu;
sig0= negx.sig;

mu1  = repmat(mu1,1,col);
sig1 = repmat(sig1,1,col);
mu0  = repmat(mu0,1,col);
sig0 = repmat(sig0,1,col);

n0= 1./(sig0+eps);
n1= 1./(sig1+eps);
e1= -1./(2*sig1.^2+eps);
e0= -1./(2*sig0.^2+eps);

x = samples.feature;
// 计算时省去了系数2*pi
p0 = exp((x-mu0).^2.*e0).*n0;
p1 = exp((x-mu1).^2.*e1).*n1;

r  = (log(eps+p1)-log(eps+p0));

FtrVal.cpp

#include <math.h>
#include "mex.h"
// compute integral img
// s(i,j) = s(i-1,j)+i(i,j)
// ii(i,j) = ii(i,j-1)+s(i,j)
// s(i,j) = s(i+j*M);
// s(0,j) = i(0,j);ii(i,0)=s(i,0)
/* Input Arguments */

/* Output Arguments */

static void getFtrVal(double samplesFtrVal[],double*iH,double *sx,double * sy,double *px, double *py, double *pw,
                      double *ph, double *pwt, int len_F,int len_S,int len_R,int M,int N)

{
    int i,j,minJ,maxJ,minI,maxI;
    int m,k;
    int x,y;
    int *temp = new int[len_F];

    // 计算每个特征包含的矩形框的个数
    for(i=0;i<len_F; i++)
    {
       m=0;
       for(j=0;j<len_R;j++)
       {
           if(px[i+j*len_F]!=0)
           {
               m = m+1;
           }
           else
           {
               break;
           }

       }
       temp[i] = m;
    }


    for(i=0;i<len_F;i++)
       for(j=0;j<len_S;j++)
       {
         m = 0;
         x = sx[j];
         y = sy[j];

         for(k=0;k<temp[i];k++)
         {
             minJ = x-1+px[i+k*len_F];
             maxJ = x-1+px[i+k*len_F]+pw[i+k*len_F]-1;
             minI = y-1+py[i+k*len_F];
             maxI = y-1+py[i+k*len_F]+ph[i+k*len_F]-1;

             m = m+pwt[i+k*len_F]*(iH[minI+minJ*M]+iH[maxI+maxJ*M]
             -iH[maxI+minJ*M]-iH[minI+maxJ*M]);

         }
         samplesFtrVal[i+j*len_F]=m;
       }
   delete []temp;

}      

// 通过mex相应的函数得到指向输入矩阵的指针和维度,并创建输出矩阵
// .m文件中px,py,pw,ph,pwt都是二维矩阵,而在.c文件中都变成了一维列向量
void mexFunction( int nlhs, mxArray *plhs[], 
                 int nrhs, const mxArray*prhs[] )

{ 
    double *iH,*sx,*sy,*px,*py,*pw,*ph,*pwt; 

    double *samplesFtrVal;

    // len_F是特征的个数,len_S是样本的个数,len_R是maxNumRect,M和N是图像的尺寸
    mwSize len_F,len_S,len_R,M,N;

    iH = mxGetPr(prhs[0]);
    sx = mxGetPr(prhs[1]);
    sy = mxGetPr(prhs[2]);
    px = mxGetPr(prhs[3]);//s.rect.x
    py = mxGetPr(prhs[4]);//s.rect.y
    pw = mxGetPr(prhs[5]);//s.rect.width
    ph = mxGetPr(prhs[6]);//s.rect.height
    pwt = mxGetPr(prhs[7]);//s.weight

    len_F = mxGetM(prhs[3]);
    len_S = mxGetN(prhs[1]);
    len_R = mxGetN(prhs[3]);

    // M和N分别表示矩阵的维度
    M = mxGetM(prhs[0]); 
    N = mxGetN(prhs[0]);

    创建新的矩阵作为函数输出结果
    plhs[0] = mxCreateDoubleMatrix(len_F,len_S, mxREAL);

    samplesFtrVal = mxGetPr(plhs[0]);

    getFtrVal(samplesFtrVal,iH,sx,sy,px,py,pw,ph,pwt,len_F,len_S,len_R,M,N);

    return;

}

integral.cpp

#include <math.h>
#include "mex.h"
// compute integral img
// s(i,j) = s(i-1,j)+i(i,j)
// ii(i,j) = ii(i,j-1)+s(i,j)
// s(i,j) = s(i+j*M);
// s(0,j) = i(0,j);ii(i,0)=s(i,0)
/* Input Arguments */

//nlhs:输出参数数目(Left-hand side),plhs:指向输出参数的指针,nrhs:输入参数数目,prhs:指向输入参数的指针
#define img_IN  prhs[0] 

/* Output Arguments */

#define ii_OUT  plhs[0]


static void integral(
                   double   ii[],
                   double   *img,
                   int M,
                   int N)
{
    int i;
    int j;
    double *s = new double[M*N];

    for(j=0; j<N; j++)
    {
        s[j*M] = img[j*M];
        for(i=1; i<M; i++)
        {
            s[i+j*M] = s[i-1+j*M] + img[i+j*M];
        }

    }


    for(i=0; i<M; i++)
    {
        ii[i] = s[i];
        for(j=1; j<N; j++)
        {

            ii[i+j*M] = ii[i+(j-1)*M] + s[i+j*M];

        }
    }


    delete []s;
    return;
}

void mexFunction( int nlhs, mxArray *plhs[], 
                 int nrhs, const mxArray*prhs[] )
{ 
    double *ii; 
    double *img; 
    mwSize M,N; 


    /* Check the dimensions of Y.  Y can be 4 X 1 or 1 X 4. */ 

    //M和N表示输入矩阵的维度
    M = mxGetM(img_IN); 
    N = mxGetN(img_IN);


    /* Create a matrix for the return argument */ 
    ii_OUT = mxCreateDoubleMatrix(M, N, mxREAL); 

    /* Assign pointers to the various parameters */ 
    ii = mxGetPr(ii_OUT);

    img = mxGetPr(img_IN); 

    /* Do the actual computations in a subroutine */
    integral(ii,img, M, N); 
    return;

}

HaarFtr.m文件的作用是对M个特征中的每个特征分别随机生成个数不定的矩阵,之后会用这些矩阵提取样本的特征。下面挑选三个特征相对应的矩阵显示:

这里写图片描述
这里写图片描述
这里写图片描述

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gguuookkaaii1234/article/details/48347867
想对作者说点什么? 我来说一句

注释生成器

2006年03月16日 42KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭