码迷,mamicode.com
首页 > 其他好文 > 详细

TLD matlab 源代码阅读(1)

时间:2014-05-18 09:25:08      阅读:440      评论:0      收藏:0      [点我收藏+]

标签:计算机视觉   matlab   tld   

最近在看视觉跟踪方面的论文,ZK博士的TLD算法作为跟踪算法的state-of-the-art,当然不得不去拜读下了,看完论文后虽然对作者整体的思想有了一个大致了解,但是对于很多细节却也还是无从得知,好在作者将自己的算法源代码全部开源,这也造福了我们这些无知者的胃口,虽然网上有几个c++版本的源码,但是matlab版本作为作者的原始版本,拿来作研究也是极好的。

通览源代码,个人感觉精髓之处无非两个函数,即:

tldInit();

tldProcessFrame();

这二者一个是用来跟踪前的初始化工作,后者当然是run-time的跟踪工作。我个人的阅读注释也将从这两个函数展开。好了,闲话少叙,下面来看看tldInit()这个函数:

进去第一个函数是

%输入:
%tld.source.bb 用户输入的目标标定框
%size(tld.source.im0.input) 输入图像的尺寸
%tld.model.min_win 目标标定框的长或宽的最小尺寸
%输出:
%tld.grid 是一个6Xn(n表示不同有效尺度下共有多少个的网格)的矩阵,前四行组成列向量表示gridbox的4个顶点,5表示索引,6表示横向的分布点数
% tld.scales 有效尺度下gridbox的高和宽,为2Xm矩阵(m表示有效的尺度的个数)
[tld.grid tld.scales] = bb_scan(tld.source.bb,size(tld.source.im0.input),tld.model.min_win);

再让我们继续进入bb_scan()函数:

bbW   = round(bb_width(bb) .* SCALE);%bb_width(bb)*(0.1615~6.1917)矩形框变尺度
bbH   = round(bb_height(bb) .* SCALE);
bbSHH = SHIFT * min(bbH,bbH);%取bbH和bbH中最小的元素组成新的矩阵,维数和原来相同 SHIFT =0.1表示变形后的矩形框的移动步长
bbSHW = SHIFT * min(bbH,bbW);

bbF   = [2 2 imsize(2) imsize(1)]‘;%[2 2 320 240]

bbs = {};
sca = [];
idx = 1;

for i = 1:length(SCALE)
    if bbW(i) < MINBB || bbH(i) < MINBB, continue; end
    
    left  = round(bbF(1):bbSHW(i):bbF(3)-bbW(i)-1);%2开头,0.1* min(bbH(i),bbW(i))为步长,320- bbW(i)-1为结尾
    top   = round(bbF(2):bbSHH(i):bbF(4)-bbH(i)-1);%2开头,0.1* min(bbH(i),bbH(i))为步长,240- bbH(i)-1为结尾
    
    grid  = ntuples(top,left);%重复功能,维度为2 X length(top)*length(left);grid的每个列向量成为网格顶点的坐标点
    if isempty(grid), continue; end
    
    bbs{end+1} =  [grid(2,:); ...%省略号为续行,bbs前四行的列向量构成一个矩形网格的四个顶点
        grid(1,:); ...
        grid(2,:)+bbW(i)-1; ...
        grid(1,:)+bbH(i)-1; ...
        idx*ones(1,size(grid,2));%坐标点对应的编号,从1开始
        length(left)*ones(1,size(grid,2));];%记录横向分布多少个点?
    sca  = [sca [bbH(i); bbW(i)]];%在原来SCA的基础上增加[bbH(i); bbW(i)]列向量,该列向量表示某个尺度因子下的gridbox的高和宽
    idx = idx + 1;
end
bb_out = [];
for i = 1:length(bbs)
    bb_out = [bb_out bbs{i}];
end
总之,该函数功能就是扫描输入图像得到很多的gridbox。

下面来到了产生特征的函数

%输入:
%tld.model.num_trees:有10棵分类树
%tld.model.num_features:每棵树里有13个特性,这里是会有13个点对的比较
%输出:
%tld.features: 4*13X10的矩阵,为fern分类器选取的随机点对,4表示一个点对的四个坐标值
tld.features  = tldGenerateFeatures(tld.model.num_trees,tld.model.num_features,1);
还是进入一看究竟:

SHI = 1/5;
SCA = 1;
OFF = SHI;

x = repmat(ntuples(0:SHI:1,0:SHI:1),2,1);%ntuples生成网格点坐标2X36矩阵,repmat表示将生成的矩阵作为初始化元素(还是矩阵)
                                         %生成一个2X1的大矩阵,这里是4X36(6*6)矩阵
x = [x x + SHI/2];%前者4X36矩阵,后者矩阵偏移0.1
k = size(x,2);%k = 36*2
%rand(1,k)随机生成都1Xk维随机分布矩阵,范围0~1
r = x; r(3,:) = r(3,:) + (SCA*rand(1,k)+OFF);%x的第3行加上随机的1X72矩阵(0~1)再加上0.2
l = x; l(3,:) = l(3,:) - (SCA*rand(1,k)+OFF);%x的第3行减去随机的1X72矩阵(0~1)再减去0.2
t = x; t(4,:) = t(4,:) - (SCA*rand(1,k)+OFF);%x的第4行减去随机的1X72矩阵(0~1)再减去0.2
b = x; b(4,:) = b(4,:) + (SCA*rand(1,k)+OFF);%x的第4行加上随机的1X72矩阵(0~1)再加上0.2

x = [r l t b];

idx = all(x([1 2],:) < 1 & x([1 2],:) > 0,1);%idx和X维数相同,如果满足条件相应元素为1,否则为0
x = x(:,idx);%挑选满足条件的所有X的列
x(x > 1) = 1;%x元素中大于1的则用1代替此元素
x(x < 0) = 0;%x元素中小于0的则用0代替此元素

numF = size(x,2);%看看现在X还有多少列

x = x(:,randperm(numF));%randperm(numF)从1~numF的数字序列随机打乱,整个表达式是指把X的列打乱
x = x(:,1:nFEAT*nTREES);%取x的前130列,x目前为4x130矩阵
x = reshape(x,4*nFEAT,nTREES);%把X塑造成4*13 X 10 的矩阵
整个函数就是生成10*13个特征点对,坐标用小数表示,表示在box的相对位置,至于为什么随机我也感觉挺困惑的,求解释啊!!

下面再来到fern(0);没什么好说的,来看下面的吧:

%输入:
%tld.source.im0.input:输入的图像
%tld.grid:6Xn(n表示不同有效尺度下共有多少个的网格)的矩阵,gridbox信息
%tld.features:4*13X10的矩阵,为fern分类器选取的随机点对,4表示一个点对的四个坐标值
%tld.scales: 有效尺度下gridbox的高和宽,为2Xm矩阵(m表示有效的尺度的个数)
%输出:
fern(1,tld.source.im0.input,tld.grid,tld.features,tld.scales); % allocate structures
进入CPP的fern

		iHEIGHT    = mxGetM(prhs[1]);//240
		iWIDTH     = mxGetN(prhs[1]);//320
		nTREES     = mxGetN(mxGetField(prhs[3],0,"x"));//10
		nFEAT      = mxGetM(mxGetField(prhs[3],0,"x")) / 4; // feature has 2 points: x1,y1,x2,y2 13
		thrN       = 0.5 * nTREES;//等于5
		nSCALE     = mxGetN(prhs[4]);//获得共有多少种尺度的BOX,即有效尺度的个数

		IIMG       = (double*) malloc(iHEIGHT*iWIDTH*sizeof(double));//积分图像变量准备
		IIMG2      = (double*) malloc(iHEIGHT*iWIDTH*sizeof(double));//平方积分图像变量准备

		// BBOX
		mBBOX      = mxGetM(prhs[2]);//等于6 
		nBBOX      = mxGetN(prhs[2]);//等于在各个有效尺度下有多少个网格
		BBOX	   = create_offsets_bbox(mxGetPr(prhs[2]));//创建保存网格数据索引等数据
        //prhs[3]是4*13X10的矩阵
        //matlab 代码中有f.x = x;f.type = ‘forest‘;见到下面就不怪了
		double *x  = mxGetPr(mxGetField(prhs[3],0,"x"));//获得特征点的指针
		double *s  = mxGetPr(prhs[4]);//各种尺度的BOX的尺寸
		OFF		   = create_offsets(s,x);//记录各个特征点对在各种尺度下box中的具体位置

		for (int i = 0; i<nTREES; i++) {
			WEIGHT.push_back(vector<double>(pow(2.0,nBIT*nFEAT), 0));//nBIT=1,权重分配权2^13
			nP.push_back(vector<int>(pow(2.0,nBIT*nFEAT), 0));//nBIT=1,nP分配2^13
			nN.push_back(vector<int>(pow(2.0,nBIT*nFEAT), 0));//nBIT=1,nN分配2^13
		}
        //static vector<vector <double> > WEIGHT;
        //static vector<vector <int> > nP;
        //static vector<vector <int> > nN;下面见怪不怪,10X 2^13的容器
		for (int i = 0; i<nTREES; i++) {
			for (int j = 0; j < WEIGHT[i].size(); j++) {
				WEIGHT[i].at(j) = 0;
				nP[i].at(j) = 0;
				nN[i].at(j) = 0;
			}
		}

来具体看看create_offset_bbox和creater_offset两个函数

	int *offsets = (int*) malloc(BBOX_STEP*nBBOX*sizeof(int));//7*nBBOX*sizeof(int)
	int *off = offsets;

	for (int i = 0; i < nBBOX; i++) {//nBBOX表示所有的网格数
		double *bb = bb0+mBBOX*i;//偏移到下一个网格的属性的向量
        //sub2idx(row,col,height)      ((int) (floor((row)+0.5) + floor((col)+0.5)*(height)))
        //floor不大于
        //bb[0]:left bb[1]top bb[2]right bb[3]bottom iHEIGHT:240 bb[4]索引从1开始 bb[5]表示number of left-right bboxes
        //以下记录索引是从左到右,从上到下方式
		*off++ = sub2idx(bb[1]-1,bb[0]-1,iHEIGHT);//左上顶点索引
		*off++ = sub2idx(bb[3]-1,bb[0]-1,iHEIGHT);//左下顶点索引
		*off++ = sub2idx(bb[1]-1,bb[2]-1,iHEIGHT);//右上顶点索引
		*off++ = sub2idx(bb[3]-1,bb[2]-1,iHEIGHT);//右下顶点索引
		*off++ = (int) ((bb[2]-bb[0])*(bb[3]-bb[1]));//记录当前网格的大小
		*off++ = (int) (bb[4]-1)*2*nFEAT*nTREES; // pointer to features for this scale
		*off++ = bb[5]; // number of left-right bboxes, will be used for searching neighbours
	}
	return offsets;

	int *offsets = (int*) malloc(nSCALE*nTREES*nFEAT*2*sizeof(int));//
	int *off = offsets;

	for (int k = 0; k < nSCALE; k++){//共有多少种尺度的BOX
		double *scale = scale0+2*k;//scale0第一种尺度的尺寸信息,*2表示列向量有2维,即高和宽,此表达式表示偏移到下一个box的尺寸向量
		for (int i = 0; i < nTREES; i++) {//10
			for (int j = 0; j < nFEAT; j++) {//13
                //x0 4*13 X 10 的矩阵
				double *x  = x0 +4*j + (4*nFEAT)*i;//4*j因为每个feature是一个4维列向量,(4*13)*i即下一棵树
                //sub2idx(row,col,height) ((int) (floor((row)+0.5) + floor((col)+0.5)*(height)))
                //scale[1]宽,scale[0]高,x[0]x坐标,x[1]y坐标
				*off++ = sub2idx((scale[0]-1)*x[1],(scale[1]-1)*x[0],iHEIGHT);//记录第一个点在该尺度BOX的具体位置,并转化为索引
				*off++ = sub2idx((scale[0]-1)*x[3],(scale[1]-1)*x[2],iHEIGHT);//记录第二个点在该尺度BOX的具体位置,并转化为索引
			}
		}
	}

好了,至此特征点的选取和gridbox的初始化已经完成了。

TLD matlab 源代码阅读(1),布布扣,bubuko.com

TLD matlab 源代码阅读(1)

标签:计算机视觉   matlab   tld   

原文地址:http://blog.csdn.net/xuchenglu/article/details/26082809

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!