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);%跟踪时用到的有效性阈值