pysot的评估代码
1.官方给出的评估代码
2.代码阅读
-
需要加载的内容
- 测试中获得的预测结果路径
--tracker_path
- 评估所用的数据集名称
--dataset
- 评估所用的跟踪器名称
--tracker_prefix
- 测试中获得的预测结果路径
-
由于权重的名称可能与输入的跟踪器名称不一致而导致的存储跟踪结果路径与理论路径发生变化时,需要将实际路径中的跟踪器名称取出替代输入的跟踪器名称。
-
理论路径:./result/VOT2018/SiamRPN 实际路径:./result/VOT2018/SiamRPN-tiny
-
这时应该将跟踪器名称转换为:
SiamRPN-tiny
-
所用代码为:
import glob import os tracker_name=glob('./result/VOT2018/SiamRPN*') #在./results/VOT2018中搜索所有的以 SiamRPN开头的文件 tracker_name=[os.path.basename(x) for x in tracker_name]
-
要测评多个跟踪器时,输入的跟踪器名称部分不填写内容即可。
-
-
获取评估数据集的路径
root
=/home/wang/pysot/testing_dataset/VOT2018
-
评估平均重叠度
acc
和跟踪失败次数num_failures
重点!!!!!!!-
读取VOT2018中的json文件,获取关于数据集信息的函数:
dataset
,包含self.video
,self.tags
,self.tracker_path
,self.tracker_name
-
创建精度鲁棒性指标函数:
ar_benchmark
def __init__(self, dataset, burnin=10): self.dataset = dataset self.burnin = burnin
-
加载跟踪结果:
tracker_trajs
(保存形式:[[跟踪器1结果],[跟踪器2结果],…]) 跟踪器1结果中每一行代表一帧的跟踪结果 (1(个跟踪器结果),300(帧),1(一帧),4(坐标))- 载入跟踪结果路径:
traj_files = glob(os.path.join(path, name, 'baseline', self.name, '*0*.txt')) #./result/VOT2018/baseline/ants1/*0*.txt
- 读取跟踪结果:左上角坐标和中心坐标。
-
计算跟踪失败帧数和跟踪失败的次数:
calculate_failures
- 记录跟踪失败的帧数:
failures
failures[i for i, x in zip(range(len(trajectory)), trajectory) if len(x) == 1 and x[0] == 2] #trajectory:(300,1,4)
- 记录跟踪失败的次数:
num_failures
num_failures=len(failures)
- 记录跟踪失败的帧数:
-
计算整个序列的平均重叠精度和重合精度:
calculate_accuracy
-
函数
calculate_accuracy
中设置参数burnin=10
:跟踪失败后必须忽略10帧---------对评估的跟踪结果进行再次筛选- 记录跟踪器进行初始化的位置:
mask=[True,False,False,True,....]
(代表第一帧和第四帧都进过初始化) - 将初始化帧及之后9帧的预测结果都设置为0,完成忽略10帧的操作。
- 于是评估的跟踪结果的形式如下:
[1,[traj1],[traj2],...,[traj10],2,0,0,0,0,1,[traj1],[traj2],....] #第1帧初始化,第12帧跟踪失败,第17帧再次初始化 # 性能平稳 前面帧效果好 [0,0,0,0,0,0,0,0,0,0,[traj10],2,0,0,0,0,0,0,0,....] #将初始化及之后9帧的结果都变为0 #那么最后计算重合精度的时候也就只用到了[traj10]
- 记录跟踪器进行初始化的位置:
-
计算重合精度
overlaps_
重点!!!!!!!!!!!- 如果预测结果中出现
0
或2
,则返回nan
- 将预测结果和真实结果转换为左上(
x1,y1
)、右上(x2,y2
)、右下(x3,y3
)、左下(x4,y4
) - 计算预测结果与真实结果的重合:
overlaps
(代码中使用的是cython语言,而且没有找到相应的代码解释) overlaps_
中的形式为:
[0,0,0,0,0,0,0,0,0,0,[traj10],2,0,0,0,0,0,0,0,0,0,0,.....] #输入 [nan,nan,nan,nan,nan,nan,nan,nan,nan,nan,0.7,nan,nan,nan,.....,0.3] #输出
- 如果预测结果中出现
-
将
overlaps
中所有除nan
的变量相加取平均,即为平均重叠精度acc
:np.nanmean(overlaps)
-
-
将**平均重叠精度
acc
**取出,放入overlaps
字典中。该字典的形式如下所示:{"ants1":0.75;"ants3":0.74,...} #当估计的跟踪器只有一个 {"ants1":0.75,0.64,0.83;"ants3":0.74,0.65,0.84;....} #当估计的跟踪器有三个
-
将**跟踪失败次数
num_failures
**取出,放入failures
字典中。该字典的形式如下所示:{"ants1":5;"ants3":4,...} #当估计的跟踪器只有一个 {"ants1":5,3,8;"ants3":4,2,7;....} #当估计的跟踪器有三个
-
-
评估
-
设置EAO基准:
EAOBenchmark
.包含self.dataset
,self.skipping=5
,self.tags=['all']
,self.low=100
,self.high=356
,self.peak=160
-
计算非重置重叠期望:
self._calculate_eao
-
加载跟踪结果:
tracker_trajs
(保存形式:[[跟踪器1结果],[跟踪器2结果],…]) 跟踪器1结果中每一行代表一帧的跟踪结果 (1(个跟踪器结果),300(帧),1(一帧),4(坐标))- 载入跟踪结果路径:
traj_files = glob(os.path.join(path, name, 'baseline', self.name, '*0*.txt')) #./result/VOT2018/baseline/ants1/*0*.txt
- 读取跟踪结果:左上角坐标和中心坐标。
-
记录所有跟踪器在所有序列下的重叠精度矩阵
all_overlaps
、跟踪失败帧数all_failures
all_overlaps
的形式: (假如需要评测两个跟踪器)
[ [序列1下跟踪器1的重叠精度矩阵], [序列1下跟踪器2的重叠精度矩阵], [序列2下跟踪器1的重叠精度矩阵], [序列2下跟踪器2的重叠精度矩阵], ........... ]
all_failures
的形式: (假如需要测评两个跟踪器)
[ [序列1下跟踪器1的跟踪失败帧位置], [序列1下跟踪器2的跟踪失败帧位置], [序列2下跟踪器1的跟踪失败帧位置], [序列2下跟踪器2的跟踪失败帧位置], ........... ]
-
从
all_failures
中获取所有跟踪器在VOT2018中的总跟踪失败次数:fragment_num
(即总连续跟踪的视频片段) -
获取VOT2018的最长序列帧数:
max_len
;序列权重seq_weight
= 1 n \frac{1}{n} n1 (假设有n个跟踪器) -
由于
all_overlaps
、all_failures
的形式如上所示,所以相对应的video_names
和gt_traj_length
的形式为:video_name= [ [序列1名称] [序列1名称] [序列2名称] [序列2名称] ........... ] gt_traj_length= [ [序列1长度] [序列1长度] [序列2长度] [序列2长度] ........... ]
-
计算
fragments
和fweights
-
设置
fragments
和fweights
的矩阵形式fragments= [ [nan,nan,nan,....,nan], [nan,nan,nan,....,nan], .......... [nan,nan,nan,....,nan] ] #行数等于所有待评估跟踪器在VOT2018中所有序列的跟踪失败次数总和,即跟踪器1的总跟踪失败 次数+跟踪器2的..+跟踪器3的..+..... #列数等于VOT2018所有序列中最长的帧数 fweights= [nan,nan,nan,.....,nan] #列数等于跟踪失败次数,即跟踪片段的数量
-
创建
for
循环
for name, traj_len, failures, overlaps in zip(video_names, gt_traj_length,all_failures, all_overlaps)
-
如果
len(failures)>0
,即跟踪器在该序列中发生了跟踪失败的情况:- 记录每段跟踪片段的起始帧位置
point
(原理:failures
记录了跟踪失败的帧位置,往后跳过5帧,就是下一段跟踪片段的起始帧位置)
points = [x+self.skipping for x in failures if x+self.skipping <= len(overlaps)] 形式:point=[0,起始位置1,起始位置2,起始位置3,.....] #值得注意的是最后5帧中就算出现了跟踪失败的现象,也不单独作为一个跟踪片段出现
-
计算跟踪失败情况下的
fragments
:-
将每个跟踪片段的重合精度取出,得到
fragment
。所谓跟踪片段是指,两次初始化之间的片段。[1,[traj1],[traj2],...,[traj10],2,0,0,0,0,1,[traj1],[traj2],....] #测试得到的预测框。可以得到1~17帧是一个跟踪片段,17~?是另一个跟踪片段 [nan,nan,nan,nan,nan,nan,nan,nan,nan,nan,0.7,nanx15,.....] #重合精度矩阵 [nanx10,0.7,nanx5] #第一个跟踪片段的重合精度矩阵 ["0"x10,0.7,"0"x5] #将第一个跟踪片段的重合精度矩阵中的nan都变为0
-
将每个跟踪片段的
fragment
添加到fragments
,得到跟踪失败情况下fragments
的形式如下所示:fragments= [ [跟踪器1在序列1下所有跟踪片段的重合精度矩阵,0,0,...], [跟踪器2在序列1下所有跟踪片段的重合精度矩阵,0,0,...], [跟踪器1在序列2下所有跟踪片段的重合精度矩阵,0,0,...], [跟踪器2在序列2下所有跟踪片段的重合精度矩阵,0,0,...], ........... ] #值得注意的是由于列数等于最长序列的长度,所以每行=重合精度矩阵+0x?
-
-
计算跟踪失败情况下的
fweights
: 值得注意的是跟踪片段越长,对应的元素越小!!!!- 若跟踪片段不是序列的最后一段,则
fweights
中的元素等于 跟 踪 片 段 长 度 ( 跟 踪 片 段 长 度 − 2 ) ∗ 1 n \frac{跟踪片段长度}{(跟踪片段长度-2)}*\frac{1}{n} (跟踪片段长度−2)跟踪片段长度∗n1(n为待评估的跟踪器数量) - 若跟踪片段是序列的最后一段,则
fweights
中的元素等于 跟 踪 片 段 长 度 ( 跟 踪 片 段 长 度 − ( 1 + 1 e − 16 ) ) ∗ 1 n \frac{跟踪片段长度}{(跟踪片段长度-(1+1e-16))}*\frac{1}{n} (跟踪片段长度−(1+1e−16))跟踪片段长度∗n1(n为待评估的跟踪器数量) - 跟踪失败情况下
fweights
的形式如下所示:
fweights= [ 跟踪器1在序列1下所有跟踪片段的权重系数, 跟踪器2在序列1下所有跟踪片段的权重系数, 跟踪器1在序列2下所有跟踪片段的权重系数, 跟踪器2在序列2下所有跟踪片段的权重系数, ......... ]
- 若跟踪片段不是序列的最后一段,则
- 记录每段跟踪片段的起始帧位置
-
如果
len(failures)>0
,即跟踪器在该序列中没有发生跟踪失败的情况:-
计算没有发生跟踪失败情况下的
fragments
和fweights
:fragments= [ [跟踪器1在序列1下的重合精度矩阵,nan,nan,...], [跟踪器2在序列1下的重合精度矩阵,nan,nan,...], [跟踪器1在序列2下的重合精度矩阵,nan,nan,...], [跟踪器2在序列2下的重合精度矩阵,nan,nan,...], ........... ] fweights= [ 1,1,1,1,1,1,1,...... ] #没有发生失败的情况下权重系数为1
-
-
综上所述,
fragments
和fweights
的形式如下所示: 假设第1序列两个跟踪都发生了跟踪失败,第2个序列两个跟踪器都没有发生跟踪失败fragments= [ [跟踪器1在序列1下所有跟踪片段的重合精度矩阵,0,0,...], [跟踪器2在序列1下所有跟踪片段的重合精度矩阵,0,0,...], [跟踪器1在序列2下的重合精度矩阵,nan,nan,...], [跟踪器2在序列2下的重合精度矩阵,nan,nan,...], .............. ] fweights= [ 跟踪器1在序列1下所有跟踪片段的权重系数, 跟踪器2在序列1下所有跟踪片段的权重系数, 1,1,1,1,1,1,1,1,1,....... #1的数量等于序列2的长度 1,1,1,1,1,1,1,1,1,....... ............. ] #序列1长33帧,两个跟踪器都发生一次跟踪失败现象;序列2长100帧,两个跟踪器都没有发生跟踪失败 fragments= [ ["0"x10,0.7,"0"x5,"0"x(300-16)], ["0"x10,0.3,0.4,"0"x5,"0"x(300-17)], ["0"x10,0.5,0.6,"0"x5,"0"x(300-17)], ["0"x10,0.4,"0"x5,"0"x(300-16)], ["nan"x10,0.3,0.4,...,"nan"x(300-100)], ["nan"x10,0.5,0.7,...,"nan"x(300-100)], .......... ] #两个跟踪器在序列1发生一次跟踪失败现象;两个跟踪器在序列2没有发生跟踪失败 fweights= [ [0,3,0.5,0.4,0.7,1,1,.....] ]
-
-
计算期望重叠精度矩阵
calculate_expected_overlap
-
设置函数
expected_overlaps
,其形式如下所示:expected_overlaps= [ 1,0,0,0,0,0,...... ] #列数等于fragments列数,即等于VOT2018中最长序列的长度
-
计算
mask
:记录fragments
矩阵每列中不为nan
的位置,形式如下所示。[nan,nan,nan,0.3,nan,0.5,nan,nan,....] #fragments矩阵中的第4列 [False,False,False,True,False,True,False,False,...] #mask的对应形式
-
计算
expected_overlaps
: (1,VOT2018最长序列的长度)-
如果
fragments
矩阵中的第i
列全为nan
,则**expected_overlaps[i]=0
** -
如果
fragments
矩阵中的第j
列不全为nan
,则**expected_overlaps[j]
为**-
获取第
j
列中不为nan
的位置(即不为nan
的行数),在此基础上,将[1:j+1]列的数据提出,得到函数fragment
只考虑跟踪失败的那些数值#假如第4列中不为nan的位置为[0,5,10],则提出的数据为fragments矩阵中第一行的2~4列数据;第六行的2~4列数据;第十一行的2~4列数据
-
求取
fragment
的平均值,获取函数seq_mean
,其形式如下:fragment= [ [0.2,0.3,0.4], [0.2,0.3,0.7] ] seq_mean = np.sum(fragment, 1) / fragment.shape[1] seq_mean=[(0.2+0.3+0.4)/3,(0.2+0.3+0.7)/3]=[0.3,0.4]
-
获得
expected_overlaps[j]
为expected_overlaps[i] = np.sum(seq_mean * fweights[mask]) / np.sum(fweights[mask]) #其中的fweights[mask]代表fragments的第j列中不为nan的位置对应在fweights矩阵中的 权重
-
-
-
计算
EAO
:-
设置函数
weight
:weight= [0,0,0,.....,1,1,1,,...1,1,0,0,.....] #列数等于VOT2018中最长序列的长度 #1的位置为:第100行到第356行
-
计算
EAO
:eao_ = np.sum(expected_overlaps[is_valid] * weight[is_valid]) / np.sum(weight[is_valid])
-
-
-
#假设最长序列长度为300,第一序列长度为33帧,跟踪失败一次的fragments形式如下: [ ["0"x10,0.7,"0"x5,"0"x(300-16)] ["0"x10,0.3,0.4,"0"x5,"0"x(300-17)] ]
#假设最长序列长度为300,第一序列长度为100帧,无跟踪失败的fragments形式如下 [ "nan"x10,0.2,0.4,0.6,....,"nan"x(300-100) ]
#假设只评估了一个序列,这个序列跟踪失败一次 fragments= [ ["0"x10,0.7,0.8,....,0,0,...], ["0"x10,0.4,0.5,....,0,0,...], ] #求解expected[12] #取出矩阵部分为: [ ["0"x9,0.7,0.8], ["0"x9,0.4,0.5] ] seq_mean=[(0.7+0.8)/11,(0.4+0.5)/11]=[0.136,0.082] fweights=[0.2,0.4] expected[12]=[0.136x0.2,0.082x0.4]=[0.0272,0.0328]
-