matlab版源程序:http://download.csdn.net/detail/cv_richie/4982673
C程序:http://download.csdn.net/detail/cv_richie/4982678
晚点我会把我注释的版本发上来。
程序运行从run_TLD.m或者run_TLD_demo.m开始,后者的功能更全,可以实现源代码作者主页上那些视频里的效果。
0. run_TLD_demo.m
程序启动的接口,这里可以设置DEMO程序的运行参数,结构体opt传递整个程序中的各种参量
.source 是图像的数据源,可以从摄像头读取图像('camera=1')和文件中读取图像序列('camera=0'),
.name 截图保存位置
初始化了全局变量tld,包括opt中的参数以及tld跟踪监测的各种数据都靠他传递。
==========================================================
1. tldDemo.m
程序运行的主题,相当于C中的MAIN函数
首先进行初始化
tldInitSource选择数据源
figure(2); set(2,'KeyPressFcn', @handleKey); 打开图像并初始化键盘输入的指针
tldInitFirstFrame 加载第一帧,加载初始框(就是检测目标框,选择摄像头用鼠标框定,选择文件读入则由文本文件中保存的信息载入)
tld = tldInit(opt,tld); %%关键!! % train initial detector 初始化detector 里面内容很多,另起介绍
===========================================================
2. tldInit.m
function tld = tldInit(opt,tld)
lk(0);
if ~isempty(tld);
handle = tld.handle;
tld = opt;
tld.handle = handle;
else
tld = opt;
end
% INITIALIZE DETECTOR =====================================================
% Scanning grid 创建扫描网格 tld.grid保存网格坐标 tld.scales保存网格尺度
[tld.grid tld.scales] = bb_scan(tld.source.bb,size(tld.source.im0.input),tld.model.min_win); %6*所有不同尺度下的网格数 1-4行为坐标 5尺度标号 6尺度下的网格列数标号
% Features
tld.nGrid = size(tld.grid,2); %tld.nGrid保存网格数量
tld.features = tldGenerateFeatures(tld.model.num_trees,tld.model.num_features,0); %初始化FERN中的pixel comparison特征对tld.featrue.x为52*10 tld.feature.type='forest'
% Initialize Detector
fern(0); % cleanup 清除FERN分类器
fern(1,tld.source.im0.input,tld.grid,tld.features,tld.scales); % allocate structures 初始化ensemble分类器
% Temporal structures
tld.tmp.conf = zeros(1,tld.nGrid);
tld.tmp.patt = zeros(tld.model.num_trees,tld.nGrid); %10*网格数
% RESULTS =================================================================
% Initialize Trajectory 初始化轨迹信息空间
tld.img = cell(1,length(tld.source.idx)); %CELL生成的是元胞
tld.snapshot = cell(1,length(tld.source.idx));
tld.dt = cell(1,length(tld.source.idx));
tld.bb = nan(4,length(tld.source.idx)); %nan生成的是空数组
tld.conf = nan(1,length(tld.source.idx));
tld.valid = nan(1,length(tld.source.idx));
tld.size = nan(1,length(tld.source.idx));
tld.trackerfailure = nan(1,length(tld.source.idx));
tld.draw = zeros(2,0);
tld.pts = zeros(2,0);
% Fill first fields
tld.img{1} = tld.source.im0;
tld.bb(:,1) = tld.source.bb;
tld.conf(1) = 1;
tld.valid(1)= 1;
tld.size(1) = 1;
% TRAIN DETECTOR ==========================================================
% Initialize structures
tld.imgsize = size(tld.source.im0.input); %tld.imgsize保存图像大小
tld.X = cell(1,length(tld.source.idx)); % training data for fern 训练ensemble的样本
tld.Y = cell(1,length(tld.source.idx));
tld.pEx = cell(1,length(tld.source.idx)); % training data for NN 训练最近邻的样本
tld.nEx = cell(1,length(tld.source.idx));
overlap = bb_overlap(tld.source.bb,tld.grid); % bottleneck 返回与bb与每个网格的重叠比
% Target (display only)
tld.target = img_patch(tld.img{1}.input,tld.bb(:,1));%分割出目标区域的图像
% Generate Positive Examples产生正样本
[pX,pEx,bbP] = tldGeneratePositiveData(tld,overlap,tld.img{1},tld.p_par_init); %PX输出前十网格的特征,每行是一个网格,10列是一层随机;pex最大网格归一化图像 bbp最大网格的坐标
pY = ones(1,size(pX,2));%正样本的正标号
% disp(['# P patterns: ' num2str(size(pX,2))]);
% disp(['# P patches : ' num2str(size(pEx,2))]);
% Correct initial bbox
tld.bb(:,1) = bbP(1:4,:);%最大重叠度的网格 程序中把制定框转化为重叠度最大的网格
% Variance threshold
tld.var = var(pEx(:,1))/2; %方差分类器阈值为最大重叠度网格方差的的一半
% disp(['Variance : ' num2str(tld.var)]);
% Generate Negative Examples
[nX,nEx] = tldGenerateNegativeData(tld,overlap,tld.img{1});%重叠度小于0.2的网格中产生
% disp(['# N patterns: ' num2str(size(nX,2))]);
% disp(['# N patches : ' num2str(size(nEx,2))]);
% Split Negative Data to Training set and Validation set
[nX1,nX2,nEx1,nEx2] = tldSplitNegativeData(nX,nEx);%负样本随机平均分为两组
nY1 = zeros(1,size(nX1,2));%负样本的负标号
% Generate Apriori Negative Examples
%[anX,anEx] = tldGenerateAprioriData(tld);
%anY = zeros(1,size(anX,2));
% disp(['# apriori N patterns: ' num2str(size(anX,2))]);
% disp(['# apriori N patches : ' num2str(size(anEx,2))]);
tld.pEx{1} = pEx; % save positive patches for later
tld.nEx{1} = nEx; % save negative patches for later
tld.X{1} = [pX nX1];
tld.Y{1} = [pY nY1];
idx = randperm(size(tld.X{1},2));
tld.X{1} = tld.X{1}(:,idx);%随机化后的初始样本集
tld.Y{1} = tld.Y{1}(:,idx);%随机化后的初始标号集
% Train using training set ------------------------------------------------
% Fern
bootstrap = 2;
fern(2,tld.X{1},tld.Y{1},tld.model.thr_fern,bootstrap); %thr_fern为0.5训练初始随机厥分类器
% Nearest Neightbour
tld.pex = [];
tld.nex = [];
tld = tldTrainNN(pEx,nEx1,tld);%训练初始NN分类器
tld.model.num_init = size(tld.pex,2);%训练后的正样本数
% Estimate thresholds on validation set ----------------------------------
% Fern
conf_fern = fern(3,nX2);%输出为输入样本的分类结果即正样本可信度,可信度越高,分类效果不好,需要更新
tld.model.thr_fern = max(max(conf_fern)/tld.model.num_trees,tld.model.thr_fern);%该阈值影响后面的学习,越大则需要更新的样本越多
% Nearest neighbor
conf_nn = tldNN(nEx2,tld);
tld.model.thr_nn = max(tld.model.thr_nn,max(conf_nn));%该阈值越大,则需要被添加的模型正样本越多
tld.model.thr_nn_valid = max(tld.model.thr_nn_valid,tld.model.thr_nn);%跟踪时用到的有效性阈值