当前位置: 首页 > news >正文

在matlab中使用UAV123官方toolkits测试自己的数据集

一、前言

最近需要将自己的跟踪代码在自己拍摄的数据集上进行测试,这里我选择使用 UAV123 官方 toolkits 进行配置。首先需要搞清楚这部分代码是如何运行的,精度图和成功率图是如何绘制出来的,然后再将自己的数据集加进去进行测试。

二、UAV123官方toolkits工作流程

本文以 UAV123 数据集为例查看 toolkits 的工作流程,共使用了 10 个跟踪器。
在绘制结果图时,首先需要将每个跟踪器在每个序列上的跟踪结果保存为一个 .mat 文件,然后运行根目录下的 perfPlot.m 文件进行结果图的绘制。直接来看 perfPlot.m 文件。

1. 准备工作

准备工作包括加载数据集中各序列的属性、绘图风格、图像序列、跟踪器等。

attPath = '...\UAV123\tracker_benchmark_v1.1\anno_uav123\att\';    % UAV123

首先需要设置一个 attpath 加载 att 文件夹。我们可以看到,att 文件夹下也放置着与数据集中图像序列数目相等的 txt 文件,且每个文件的名称即为图像序列的名称。与标注目标位置的 txt 文件不同,这里的 txt 文件中只含有 12 个非 0 即 1 的数字,分别对应着 UAV123 数据集的 12 种属性。若该序列包含某种属性,则该属性位置对应的值即为 1,否则为 0。12 种属性分别为:

%UAV123
attName={'Scale Variation' 'Aspect Ratio Change' 'Low Resolution' 'Fast Motion' 'Full Occlusion' 'Partial Occlusion' 'Out-of-View' 'Background Clutter' 'Illumination Variation' 'Viewpoint Change' 'Camera Motion' 'Similar Object'};attFigName={'SV'	'ARC'	'LR'	'FM'	'FOC'	'POC'	'OV'	'BC'	'IV'	'VC'	'CM'	'SOB'};

这里我根据 UAV123.json 文件中的信息对每种属性包含的图像序列进行了整理:

尺度变化(Scale Variation)group1_2、car10、person8_1、person12_2、car3_s、car1_1、group3_1、car11、group1_3、group1_1、person11、car13、person8_2、group3_3、car1_3、car1_2、car1_s、group3_2、wakeboard10、car12、person10、group1_4、person15、car17、car15、person14_1、uav8、group3_4、person16、car14、person3、car3、car6_5、wakeboard1、group2_3、group2_2、car6_4、car2、car2_s、wakeboard2、group2_1、wakeboard3、car5、wakeboard7、car6_3、car6_2、wakeboard6、person17_2、car4、truck4_2、building2、wakeboard4、boat9、car4_s、boat8、car6、wakeboard5、person17_1、person17_1、truck4_1、car7、building3、person19_3、person1_s、wakeboard8、boat5、truck1、car8_2、boat4、wakeboard9、person19_2、car9、boat6、truck2、car8_1、boat7、person3_s、person19_1、bird1_3、boat3、person7_2、person5_1、bike1、boat2、bird1_2、person7_1、bike3、bike2、boat1、bird1_1、uav5、uav4、car18、person18、uav6、uav7、person21、uav3、car16_2、uav1_3、uav1_2、uav2、person4_2、person20、person9、person22、car16_1、uav1_1、person23、person4_1
纵横比变化(Aspect Ratio Change)person8_1、person12_2、group3_1、group1_3、person11、person8_2、group3_3、car1_3、car1_2、car1_s、group3_2、car12、group1_4、car17、car15、person14_1、group3_4、person16、car14、car6_5、wakeboard1、group2_3、car2、wakeboard2、group2_1、wakeboard3、wakeboard7、car6_3、car6_2、wakeboard6、person17_2、car4、wakeboard4、boat9、car4_s、boat8、wakeboard5、person17_1、car7、person19_3、wakeboard8、boat5、truck1、boat4、person19_2、car9、truck2、car8_1、boat7、person3_s、person19_1、bird1_3、boat3、person7_2、bike1、bird1_2、person7_1、bike2、bird1_1、car18、person18、person21、car16_2、uav1_3、uav1_2、person20、person9、uav1_1
低分辨率(Low Resolution)group3_1、car11、group1_3、car13、car1_2、group3_2、wakeboard10、car12、car17、car15、person14_1、uav8、group3_4、car14、car3、group2_3、car2、wakeboard3、wakeboard6、car4、truck4_2、boat9、boat8、wakeboard5、truck4_1、person19_3、wakeboard8、wakeboard9、car9、truck3、truck2、bird1_3、bird1_2、bike3、bike2、bird1_1、uav5、uav4、uav6、uav7、person21、uav3、uav1_3、uav1_2、uav2、person22、car16_1、uav1_1
快速运动(Fast Motion)person8_1、car3_s、car1_s、car2_s、wakeboard2、wakeboard6、car4_s、wakeboard5、person19_3、person1_s、person19_2、car9、boat7、person3_s、person19_1、bird1_3、person7_2、bike1、bird1_2、person7_1、bird1_1、car18、uav6、uav3、car16_2、uav1_3、car16_1、person23
全部遮挡(Full Occlusion)person8_1、person12_2、car11、car1_3、car1_2、group3_2、car12、person10、person14_1、group3_4、person16、car14、group2_3、group2_2、car2、group2_1、person17_1、car7、person19_3、person19_2、person19_1、bird1_3、bird1_2、person7_1、bike2、bird1_1、uav6、uav7、uav1_3、uav1_2、uav2、person9、uav1_1
局部遮挡(Partial Occlusion)group1_2、car10、person8_1、person12_2、car3_s、group3_1、car11、person13、group1_3、group1_1、person11、person8_2、group3_3、car1_3、car1_2、car1_s、group3_2、car12、person10、group1_4、person14_3、person15、car15、person14_1、group3_4、person16、car14、car3、car6_5、group2_3、group2_2、car2、car2_s、group2_1、car6_2、person17_2、car4、truck4_2、boat9、wakeboard5、person17_1、truck4_1、car7、person19_3、person1_s、truck1、person19_2、car9、truck3、truck2、car8_1、person3_s、person19_1、bird1_3、person7_2、bird1_2、person7_1、bike3、bike2、bird1_1、person2_2、person18、uav6、uav7、person21、uav1_3、uav1_2、uav2、person20、person9、car16_1、uav1_1、person4_1
移出视野(Out-of-View)person8_1、person8_2、car1_3、car1_s、person10、person14_3、car14、car3、car6_5、car2、car6_2、person19_3、person19_2、car8_1、person3_s、person19_1、bird1_3、person7_2、bird1_2、person7_1、bird1_1、person2_2、person18、uav1_3、uav1_2、person20、person9、car16_1、uav1_1、person4_1
背景杂波(Background Clutter)person13、group3_3、person12_1、group3_2、person14_2、person14_3、person14_1、uav8、group3_4、person16、group2_3、group2_1、person17_2、truck3、bike2、uav5、uav7、person21、uav1_3、uav1_2、uav1_1
光照变化(Illumination Variation)person12_2、car3_s、person13、person12_1、car1_s、group3_2、group1_4、uav8、group3_4、person16、wakeboard1、group2_3、car6_4、car2_s、car6_3、wakeboard6、person17_2、car4_s、wakeboard5、person17_1、person1_s、wakeboard8、car8_2、boat4、person3_s、bike1、bike2、person21、uav1_3、uav1_2、uav1_1
视角变化(Viewpoint Change)car3_s、car11、person13、group1_3、person6、person11、person12_1、car1_3、car1_2、car1_s、car12、person10、group1_4、person14_3、car17、car14、car6_5、group2_3、group2_2、car6_4、car2_s、wakeboard2、group2_1、wakeboard3、wakeboard7、car6_3、car6_2、wakeboard6、truck4_2、wakeboard4、boat9、car4_s、boat8、wakeboard5、car7、person19_3、person1_s、wakeboard8、boat5、truck1、boat4、car8_1、boat7、boat3、person7_2、person5_1、bike1、person7_1、person5_2、car18、person18、person21、car16_2、uav1_3、uav1_2、person20、person9、person22、car16_1、uav1_1
相机运动(Camera Motion)person8_1、person12_2、car3_s、car1_1、car11、group1_3、person6、car13、group3_3、person12_1、car1_2、car1_s、group3_2、person10、group1_4、person1、person14_2、person14_3、car17、person14_1、group3_4、person16、car14、person3、car3、car6_5、group2_3、group2_2、car6_4、car2、car2_s、wakeboard2、group2_1、wakeboard3、building5、car6_2、wakeboard6、person17_2、car4、car4_s、wakeboard5、person19_3、person1_s、wakeboard8、wakeboard9、person19_2、car9、car8_1、boat7、person3_s、person19_1、bird1_3、person7_2、bike1、person7_1、person2_2、car18、person18、uav6、person2_1、uav3、car16_2、uav1_3、person4_2、person20、person9、car16_1、uav1_1、person23、person4_1
相似目标(Similar Object)group1_2、car10、car1_1、group3_1、car11、group1_3、group1_1、person11、group3_3、car1_3、car1_2、group3_2、car12、person10、group1_4、person15、car15、group3_4、car3、group2_3、group2_2、car6_4、car2、group2_1、car6_3、car4、car7、building3、person19_3、car8_2、car9、car8_1、bike1、uav4、uav6、person21、person20、person9、person4_1

然后是设定绘图风格、加载图像序列和跟踪器等等,其中,加载的图像序列包括 …/util/configSeqs.m 中设置的所有属性:
在这里插入图片描述
跟踪则包含我们在 …/util/configTrackers.m 中设置的两种属性:
在这里插入图片描述
然后,这里设置了一个元胞数组 nameTrkAll,用来存储所有跟踪器在图片中显示的名称:

nameTrkAll=cell(numTrk,1);
for idxTrk=1:numTrkt = trackers{idxTrk};nameTrkAll{idxTrk}=t.namePaper;
end

接下来,定义了一个元胞数组 nameSeqAll,用来存储所有图像序列的名称,以及一个 double 数组,用来存储每个图像序列的长度,以及一个空数组 att,用来存储每个序列的属性。attNum 则用来记录该数据集共有集中属性。这里是 12 种。


nameSeqAll=cell(numSeq,1);
numAllSeq=zeros(numSeq,1);att=[];
for idxSeq=1:numSeqs = seqs{idxSeq};nameSeqAll{idxSeq}=s.name;s.len = s.endFrame - s.startFrame + 1;numAllSeq(idxSeq) = s.len;att(idxSeq,:)=load([attPath s.name '.txt']);
endattNum = size(att,2);

然后设置 figPath 和 perfMatPath,分别为存储结果图的路径和存储 距离精度及重叠精度 mat 文件的路径。

接下来,设置度量类型、评估类型、排名类型,这里分别设置为距离误差、重叠率,一次性评估,精度:


metricTypeSet = {'error', 'overlap'};
evalTypeSet = {'OPE'}; %'SRE', 'OPE'rankingType = 'threshold'; %AUC, threshold

然后设置跟踪器的数量同时选定绘图风格。

接下来设置记录重叠率的阈值集 thresholdSetOverlap,以及记录误差的阈值集 thresholdSetError。

thresholdSetOverlap = 0:0.05:1;
thresholdSetError = 0:50;

2. 绘制精度曲线

在接下来的循环中,首先计算的是跟踪精度,以精度图的形式呈现。
在绘制精度图的过程中,首先将阈值集设置为误差阈值集,然后设置排名 rankIdx ,以及 x、y 坐标轴名称

case 'error'thresholdSet = thresholdSetError;rankIdx = 21;xLabelName = 'Location error threshold';yLabelName = 'Precision';

接下来,利用一次性评估标准计算跟踪误差,首先确定保存误差结果的 mat 文件的名称及存放地址:

evalType = evalTypeSet{j};%SRE, TRE, OPE
plotType = [metricType '_' evalType];
switch metricTypecase 'overlap'titleName = ['Success plots on UAV123 '];case 'error'titleName = ['Precision plots on UAV123 '];
end
dataName = [perfMatPath 'aveSuccessRatePlot_' num2str(numTrk) 'alg_'  plotType '.mat'];

若不存在则创建:

if ~exist(dataName)genPerfMat(seqs, trackers, evalType, nameTrkAll, perfMatPath);
end   

我们已经知道后面的跟踪精度图都是根据这个 mat 文件中的数据绘制的,那我们先来看一下这个文件是如何生成的:

pathAnno = '.../UAV123/tracker_benchmark_v1.1/anno_uav123/';    % UAV123
numTrk = length(trackers);
thresholdSetOverlap = 0:0.05:1;
thresholdSetError = 0:50;

首先需要明确每个序列中记录目标真值框文件的位置,然后是跟踪器的数目,以及重叠率阈值集和误差阈值集。
然后根据评估标准明确选取哪个位置的跟踪结果:

switch evalTypecase 'SRE'rpAll=['.\results\results_SRE\'];case {'TRE'}rpAll=['.\results\results_TRE\'];case {'OPE'}rpAll=['.\results\results_OPE\'];
end

然后则按照 configSeqs.m 中的序列顺序依次进行计算。首先初始化一些基本信息,包括序列的帧数、名称等等:

s = seqs{idxSeq};
s.len = s.endFrame - s.startFrame + 1;
s.s_frames = cell(s.len,1);
nz	= strcat('%0',num2str(s.nz),'d'); %number of zeros in the name of image

其中 s 包含下列信息:
在这里插入图片描述
记录序列中每张图片的位置:

for i=1:s.lenimage_no = s.startFrame + (i-1);id = sprintf(nz,image_no);s.s_frames{i} = strcat(s.path,id,'.',s.ext);
end

读取真值框,设置采样片段数,然后

rect_anno = dlmread([pathAnno s.name '.txt']);
numSeg = 20;
[subSeqs, subAnno]=splitSeqTRE(s,numSeg,rect_anno);

来看一下这个 splitSeqTRE 函数。
splitSeqTRE 函数将每个序列20个片段,首先,排除所有occ/不可见帧,然后进行采样:

Idx = 1:seq.len;
for j = 1:size(IdxExclude,1)Idx(IdxExclude(j,1):IdxExclude(j,2))=0;
end
Idx = Idx(find(Idx>0));for i=1:length(Idx)r = rect_anno(Idx(i),:);if r(1)<=0 | r(2)<=0 | r(3)<=0 | r(4)<=0 | isnan(sum(r))Idx(i) = 0;end
endIdx = Idx(find(Idx>0));

上面这段代码即将所有不可见帧排除了。

设置数组 startFrIdxOne 记录每组图片的其实帧号:

        
for i = length(Idx):-1:1if seq.len - Idx(i) + 1 >= minNumendSeg = Idx(i);endSegIdx = i;break;end
endstartFrIdxOne = [floor(1:endSegIdx/(segNum-1):endSegIdx) endSegIdx] ;

然后将序列分为 20 组图片,变量 subAnno 记录每组图片的的真值框,变量 subSeqs 记录每组图片的信息:

for i = 1:length(startFrIdxOne)index = Idx(startFrIdxOne(i));subS.path = seq.path;subS.nz = seq.nz;subS.ext = seq.ext;subS.startFrame = index+seq.startFrame-1;subS.endFrame = seq.endFrame;subS.len = subS.endFrame - subS.startFrame + 1;subS.annoBegin = seq.startFrame;subS.init_rect = rect_anno(index,:);anno = rect_anno(index:end,:);subS.s_frames = seq.s_frames(index:end);subS.name = seq.name;
%     subS.nameIdx = [seq.name '_' num2str(i)];subAnno{i} = anno;subSeqs{i}=subS;
end

这里每组图片是由先前计算的 startFrIdxOne 到最后一帧的信息。

回到 genPerfMat 函数,按照跟踪器的顺序依次计算误差和重叠率:

t = trackers{idxTrk};load([rpAll s.name '_' t.name '.mat'])
disp([s.name ' ' t.name]);aveCoverageAll=[];
aveErrCenterAll=[];
errCvgAccAvgAll = 0;
errCntAccAvgAll = 0;
errCoverageAll = 0;
errCenterAll = 0;lenALL = 0;
switch evalTypecase 'SRE'idxNum = length(results);anno=subAnno{1};case 'TRE'idxNum = length(results);case 'OPE'idxNum = 1;anno=subAnno{1};
end

运行到这里发现虽然 splitSeqTRE 函数将图像序列分为了 20 个片段,但使用 OPE 的评估方式只 用到了 subAnno{1},也就是剩余的都没用到,而 subAnno{1} 就是所有图片的真值框。

设置数组 successNumOverlap 记录不同重叠率阈值下的成功率数量,设置数组 successNumErr 记录不同误差阈值下的成功率数量:

successNumOverlap = zeros(idxNum,length(thresholdSetOverlap));
successNumErr = zeros(idxNum,length(thresholdSetError));

加载跟踪结果:

res = results{idx};

计算误差:

[aveCoverage, aveErrCenter, errCoverage, errCenter] = calcSeqErrRobust(res, anno);

直接来看这个 calcSeqErrRobust 函数。首先对跟踪结果进行了一个处理,对跟踪结果为 NaN 或者跟踪框尺度为负值且真值框不为 NaN 的情况,将跟踪结果改为前一帧的跟踪结果:

if strcmp(results.type,'rect')for i = 2:seq_lengthr = results.res(i,:);r_anno = rect_anno(i,:);if (isnan(r) | r(3)<=0 | r(4)<=0)&(~isnan(r_anno))results.res(i,:)=results.res(i-1,:);endend
end

计算真值框的中心坐标:

centerGT = [rect_anno(:,1)+(rect_anno(:,3)-1)/2 rect_anno(:,2)+(rect_anno(:,4)-1)/2];

将第一帧的真值框坐标赋给第一帧的跟踪结果并计算跟踪器跟踪的目标框中心坐标:

rectMat(1,:) = rect_anno(1,:);
center = [rectMat(:,1)+(rectMat(:,3)-1)/2 rectMat(:,2)+(rectMat(:,4)-1)/2];

计算每一帧的中心距离误差:

errCenter = sqrt(sum(((center(1:seq_length,:) - centerGT(1:seq_length,:)).^2),2));

将真值框大于 0 的帧的跟踪结果和真值框值送入 calcRectInt 函数计算重叠率 tmp:

index = rect_anno>0;
idx=(sum(index,2)==4);
tmp = calcRectInt(rectMat(idx,:),rect_anno(idx,:));

计算平均重叠率和平均中心距离误差:

aveErrCoverage = sum(errCoverage(idx))/length(idx);
aveErrCenter = sum(errCenter(idx))/length(idx);

按照之前设置的重叠率阈值分别计算该序列成功的帧数:

for tIdx=1:length(thresholdSetOverlap)successNumOverlap(idx,tIdx) = sum(errCoverage >thresholdSetOverlap(tIdx));
end

按照之前设置的中心距离误差阈值分别计算该序列成功的帧数:

for tIdx=1:length(thresholdSetError)successNumErr(idx,tIdx) = sum(errCenter <= thresholdSetError(tIdx));
end

计算成功率和跟踪精度每个阈值处的值:

if strcmp(evalType, 'OPE')aveSuccessRatePlot(idxTrk, idxSeq,:) = successNumOverlap/(lenALL+eps);aveSuccessRatePlotErr(idxTrk, idxSeq,:) = successNumErr/(lenALL+eps);

这里 eps 的目的是什么呢?
到这里第一个序列第一个跟踪器的成功率和跟踪精度就计算结束了。依次循环直至在所有序列上计算完所有跟踪器的结果。
将成功率和跟踪精度存至 perMat 文件夹下:

dataName1=[perfMatPath 'aveSuccessRatePlot_' num2str(numTrk) 'alg_overlap_' evalType '.mat'];
save(dataName1,'aveSuccessRatePlot','nameTrkAll');dataName2=[perfMatPath 'aveSuccessRatePlot_' num2str(numTrk) 'alg_error_' evalType '.mat'];
aveSuccessRatePlot = aveSuccessRatePlotErr;
save(dataName2,'aveSuccessRatePlot','nameTrkAll');

genPerfMat 函数执行完毕,回到 perfPlot 函数。

加载中心距离误差值,设置结果图名称:

load(dataName);
figName= [figPath 'quality_plot_' plotType '_' rankingType];

由 plotDrawSave 函数绘制曲线图。
来看一下 plotDrawSave 函数。
首先需要按照跟踪器的顺序依次统计中心距离误差小于 20 个像素的帧数所占百分比,即距离精度:

for idxTrk=1:numTrk%each row is the sr plot of one sequencetmp=aveSuccessRatePlot(idxTrk, idxSeqSet,:);aa=reshape(tmp,[length(idxSeqSet),size(aveSuccessRatePlot,3)]);aa=aa(sum(aa,2)>eps,:);bb=mean(aa);switch rankingTypecase 'AUC'perf(idxTrk) = mean(bb);case 'threshold'perf(idxTrk) = bb(rankIdx);end
end

这里 bb 即为每个跟踪器在 123 个序列上每个阈值下的平均中心距离误差,rankIdx 值为 21,bb 中第 21 个阈值刚好对应 20 个像素,即通用阈值。
对跟踪器根据 20 个像素的公共阈值进行排名:

[tmp,indexSort]=sort(perf,'descend');

其中 tmp 为排名之后的分数,indexSort 为排名之后各跟踪器对应的顺序。
然后按照排序后的顺序从高到低依次绘制精度曲线:

for idxTrk=indexSort(1:rankNum)tmp=aveSuccessRatePlot(idxTrk,idxSeqSet,:);aa=reshape(tmp,[length(idxSeqSet),size(aveSuccessRatePlot,3)]);aa=aa(sum(aa,2)>eps,:);bb=mean(aa);switch rankingTypecase 'AUC'score = mean(bb);tmp=sprintf('%.3f', score);case 'threshold'score = bb(rankIdx);tmp=sprintf('%.3f', score);endh(i) = plot(thresholdSet,bb,'color',plotDrawStyle{i}.color, 'lineStyle', plotDrawStyle{i}.lineStyle,'lineWidth', 4,'Parent',axes1);hold oni=i+1;
end

精度曲线绘制完成。

3. 绘制每种属性下的精度曲线

回到 perfPlot 函数,依次绘制每种属性的精度曲线图。
首先需要找出每种属性对应的序列:

idxSeqSet=find(att(:,attIdx)>attTrld);

然后同样进入 plotDrawSave 函数,分别绘制精度曲线图。

成功率曲线的绘制过程与精度曲线类似。

三、测试自己的数据集

1. 数据集标注

首先需要对数据集进行标注,标注过程就不再赘述了。数据集中的每个序列应该对应一个 .txt 格式的标注文档,文档中包含了每张图片中目标框的左上角和目标框的大小。

2. 配置数据集

仿照 UAV123 数据集将图像序列和标注数据进行存储。例如,我的数据集命名为 UAV_seq ,那么首先建立一个名为 UAV_seq 的文件夹,文件夹内容如下:

在这里插入图片描述
data_seq 文件夹中为每个图像序列的名称,每个文件夹下为对应的图像序列;anno 文件夹下则放置每个图像对应的 txt 文件。

3. 在 configSeqs 中添加数据集信息

仿照 seqUAV123 在 …/util/configSeqs.m 文件中添加 UAV_seq 的相关信息,包括数据集中图像序列的名称、路径、开始、结束帧数等等。

4.

相关文章:

  • 鼠标滚动字体缩放
  • STM32 USB配置详解
  • 从数据到决策:如何使用Python进行自动驾驶数据分析
  • 图论---拓扑排序(DFS)
  • 计算机视觉进化论:YOLOv12、YOLOv11与Darknet系YOLOv7的微调实战对比
  • Linux运维——Vim基础
  • 如何搭建spark yarn模式的集合集群
  • 搭建 Spark YARN 模式集群指南
  • 集成学习详解
  • Darvas Box黄金交易算法详解:基于XAU/USD的实战应用
  • Web 基础与Nginx访问统计
  • lmms-eval--微调实战笔记
  • 如何实现Kafka的Exactly-Once语义?
  • 输出圆周率的前n位数字
  • 含锡废水综合治理技术解析
  • Electron 入门指南
  • 【ACL系列论文写作指北08-图表设计规范】-让数据与结构一目了然
  • 深入探究C++ 中的stack、queue和deque
  • 数据结构之顺序表
  • Flask + ajax上传文件(四)--数据入库教程
  • 李祥翔评《孔子哲学思微》︱理性秩序与美学秩序的碰撞
  • 美情报机构攻击中国大型商用密码产品提供商,调查报告公布
  • 影子调查|23岁男子驾照拟注销背后的“被精神病”疑云
  • 别让心脏“饿肚子”,心肌缺血全解析
  • 哈马斯官员:只要以军持续占领,哈马斯就不会放下武器
  • 特朗普将举行集会庆祝重返白宫执政百日,美媒:时机不当