这两个问题我自己刚开始也是很困扰,但是经过一番折腾终于出来解决方法了,看完这一篇你也可以解决上面两个问题!!
去官网首页可以看到评估代码是在MATLAB环境下的,虽然自己觉得自己matlab学过,但是还是很多需要查考和拾起,所以选择了他的python版本的评估代码,既然也是官网上放出来的,也是具有权威性的,只不过哪个语言的结果跑出来会好点,这个还需进一步实验。
注:个人感觉matlab版本迟早要去了解的,因为之后对于LaSOT这种更大的数据集也是matlab下的,所以搞懂OTB benchmark的matlab版本,对之后其余数据集评估是大有益处的,好了,废话不多说,上干货!
先去download代码:https://github.com/jwlim/tracker_benchmark,有41.6M,难下的话可以去这里下,代码中有几处bug,等一下再说。我在win10上试验的,ubuntu应该也没有问题!
可以在README.md看到,需要安装的包是:Matlab Engine for python、matplotlib、numpy、Python Imaging Library (PIL)
,并且这个代码是python 2.7.10
下的,可以用anaconda安装conda环境:
我在ubuntu下更高版本的anaconda下似乎找不到python2.7.10了,通过conda search python发现最低也是python2.7.13,证明也是可以的
conda create -n py27 python=2.7.10 matplotlib=2.2.2 numpy=1.14.3 pillow=5.1.0
# 这样就安装好了一个名字为'py27'的conda环境,激活一下:
conda activate py27
环境创建好之后,来看一下几处需要修改的bug:
attr = Attribute(**j)
改成attr = attr = Score(**j)
,因为代码里面没有Attribute类。precisionList
,所以需要在55-56行之间插入一句:precisionList = []
,缩进与55行一样这个数据集因为评估需要,对于数据集有一定的格式安排,并不是官网上一个一个序列下载就好的,有三种方法准备:
butil.setup_seqs(loadSeqs)
,会去这样的网址下载:http://cvlab.hanyang.ac.kr/tracker_benchmark/seq_new/seqname.zip
。注意官网上下载地址是http://cvlab.hanyang.ac.kr/tracker_benchmark/seq/seqname.zip
,这里新的主要是一些序列目录下不仅有img和groundtruth_rect.txt文件,还有init_omit.txt文件,如果你网络可以,那这样下载下来是最省事的。Jogging
下的img复制到代码中的data中的Jogging-1
和Jogging-2
下,把groundtruth_rect.1.txt
和jogging-1.txt
复制到Jogging-1
下,分别重命名为groundtruth_rect.txt
和init_omit.txt
;同理把groundtruth_rect.2.txt
和jogging-2.txt
复制到Jogging-2
下,同样分别重命名为groundtruth_rect.txt
和init_omit.txt
。Skating2
下的img复制到代码中的data中的Skating2-1
和Skating2-2
下,把groundtruth_rect.1.txt
复制到Skating2-1
下,重命名为groundtruth_rect.txt
;同理,把groundtruth_rect.2.txt
复制到Skating2-2
下,重命名为groundtruth_rect.txt
。Human4
下的img复制到代码中的data中的Human4-2
下,然后把groundtruth_rect.2.txt
复制到Human4-2
下,重命名为groundtruth_rect.txt
。init_omit.txt
那么现在前期代码和数据集都已经准备好了!
相信无论什么语言写的跟踪器,预测结果就是一个序列中每帧物体的坐标,而OTB里面的GT BBox的形式是ltwh
的,我这里举例的是我这篇博客【siamfc-pytorch代码讲解(三):demo&track】里面的结果:
跟踪结果文件目录结构:
├── SiamFC
│ ├── Basketball.txt
│ ├── ...
│ ├── Woman.txt
│ ├── times
│ │ ├── Basketball_time.txt
│ │ ├── ...
│ │ ├── Woman_time.txt
每一个序列txt文件里面都是N×4的坐标,比如Basketball.txt里面如下图所示:
在代码根目录下新建两个py文件:save_to_json.py
和util.py
,分别复制以下代码,其中txt_Results
需要替换成你自己的路径:
save_to_json.py:
from scripts import *
from config import *
from util import compare_name, calcu_speed, load_seq_result
loadSeqs = 'tb100'
evalType = 'OPE'
tracker = 'SiamFC'
# replace your own path
txt_Results = 'C:\\Users\\Ezra\\Desktop\\SiamFC'
if SETUP_SEQ:
print 'Setup sequences ...'
"""
Doing in setup_seqs:
1. check integrity of data, if not, download all
2. write cfg.json and attrs.txt in each seq directory
"""
butil.setup_seqs(loadSeqs)
# 'otb50', 'otb100' transform to corresponding seqs name list
seqNames = butil.get_seq_names(loadSeqs)
# load from saved cfg.json and return list contain Class Sequence instances
seqs = butil.load_seq_configs(seqNames)
resNames = os.listdir(txt_Results)
resNames.remove('times')
resNames = [res_name[:-4] for res_name in resNames]
print "=========================================================="
isSameName = compare_name(resNames, seqNames)
if isSameName:
for s in seqs:
seqResults = []
res_type = 'rect'
# fps is optinal
fps = round(calcu_speed(txt_Results, s.name), 3)
boxes = load_seq_result(txt_Results, s.name)
res = boxes.tolist()
# for OPE
r = Result(tracker, s.name, s.startFrame, s.endFrame,
res_type, evalType, res, fps, None)
seqResults.append(r)
if SAVE_RESULT:
print "Now write to results/{0}/{1}/{2}.json".format(evalType, tracker, s.name)
# 'results/evalType/Tracker/seqName.json'
butil.save_seq_result(seqResults)
print "Have written all seqs!"
util.py:
import os
import numpy as np
DIFF_NAMES = ('Human4-2', 'Jogging-1', 'Jogging-2',
'Skating2-1', 'Skating2-2')
def _convert_name(oldname):
newname = None
if oldname == 'Human4-2':
newname = 'Human4'
elif oldname == 'Jogging-1':
newname = 'Jogging.1'
elif oldname == 'Jogging-2':
newname = 'Jogging.2'
elif oldname == 'Skating2-1':
newname = 'Skating2.1'
elif oldname == 'Skating2-2':
newname = 'Skating2.2'
return newname
def compare_name(resnames, seqnames):
flag = True
assert len(resnames) == len(seqnames),\
'The length between resnames and seqnames is not same!'
for seqName in seqnames:
if seqName in DIFF_NAMES:
seqName = _convert_name(seqName)
if seqName not in resnames:
print seqName + ' is not in resnames'
flag = False
break
return flag
def calcu_speed(timetxtdir, seq_name):
speed = 0.0
if seq_name in DIFF_NAMES:
seq_name = _convert_name(seq_name)
time_file = os.path.join(
timetxtdir, 'times/%s_time.txt' % seq_name)
if os.path.isfile(time_file):
times = np.loadtxt(time_file)
times = times[times > 0]
if len(times) > 0:
speed = np.mean(1. / times)
return speed
def load_seq_result(boxtxtdir, seq_name):
if seq_name in DIFF_NAMES:
seq_name = _convert_name(seq_name)
record_file = os.path.join(
boxtxtdir, '%s.txt' % seq_name)
boxes = np.loadtxt(record_file, delimiter=',')
return boxes
然后:
save_to_json.py
,在results/OPE/
下就会出现SiamFC文件夹,里面是各个序列的json文件。python run_trackers.py -t SiamFC -s tb100 -e OPE
,中间会提示Input Test name :
可以输入tb100
,tb50
,cvpr13
作为文件夹命名的一部分,因为最后画图路径读取需要Result of Sequences -- 'SiamFC'
'Basketball' aveCoverage : 38.878% aveErrCenter : 75.946
...
'Woman' aveCoverage : 50.644% aveErrCenter : 4.957
Result of attributes -- 'SiamFC'
'ALL' overlap : 64.6% failures : 3.4
'BC' overlap : 63.3% failures : 4.9
'DEF' overlap : 59.8% failures : 4.2
'FM' overlap : 63.8% failures : 3.7
'IPR' overlap : 61.8% failures : 3.9
'IV' overlap : 61.6% failures : 4.3
'LR' overlap : 64.7% failures : 4.3
'MB' overlap : 67.2% failures : 3.3
'OCC' overlap : 63.3% failures : 4.0
'OPR' overlap : 62.6% failures : 3.8
'OV' overlap : 61.3% failures : 5.0
'SV' overlap : 63.8% failures : 3.6
python draw_graph.py
就可以得到成功率图(Success Plot):默认只画前10名的,其余的以灰色虚线画出来,准确率图 (Precision Plot)也是这样,可以看到咋们自己的跟踪器结果已经加进去和别的跟踪器有比较了,注意这里分数已经乘以100了【我这里训练结果比较差,仅供参考,跟GOT-10k里面的ExperimentOTB出来的0.529相差不大】python draw_graph.py precision
就可以得到准确率图 (Precision Plot):2020/05/09更新:把util.py 59行的dtype=int删除
2020/05/20更新:我想试试两个语言的官方评测结果是否会有出入,matlab的结果由我这篇博客【siamfc-pytorch代码讲解(三):demo&track】里面给出了,我就把.mat文件转换成.txt文件,用这个又尝试了一下,想不到python的结果没有matlab的好:success:0.582->0.5788;precision:0.771->0.76。下图为证:
有点不知道为什么会掉点,按理应该不会差太多的,我保证mat转txt没有失精度,难道是python和matlab里面计算的细节不太一样?或者两者计算保留精度不同?还请有尝试过的大佬提个醒
2020/05/24更新:提供一下txt转mat的代码,具体使用方法可以去见我的这篇博客:【siamfc-pytorch代码讲解(三):demo&track】:
clear all;clc;
root = 'D:...\your_txt_path\';
dst = 'D:...\your_mat_save_path\';
if ~exist(dst, 'dir')
mkdir(dst);
end
% 下面这几句是为了获取一个目录下的txt文件名列表
fileFolder = fullfile(root);
dirOutput = dir(fullfile(fileFolder, '*.txt'));
fileNames={dirOutput.name}; % 1*100 cell
numFile = length(fileNames);
for idxFile = 1:numFile
path = [root fileNames{idxFile}];
res = load(path);
[seq_l, xywh] = size(res);
results{1}.res = res;
results{1}.type = 'rect';
results{1}.len = seq_l;
seq_name = fileNames{idxFile}(1:end-4);
sprintf(['now trans ' seq_name ' from txt to mat'])
% 将需要的结构体结果写成mat格式
save([dst seq_name '_SiamfcppCiresnet22Atten.mat'], 'results');
end
2020/07/06更新:放一下mat转txt的代码,有需要可以取用:
root = 'C:\Users\Ezra\Desktop\results_SiamFC-3s_OTB-100\';
dst = 'C:\Users\Ezra\Desktop\SiamFC-3s_OTB-100-txt\';
if ~exist(dst, 'dir')
mkdir(dst);
end
fileFolder = fullfile(root);
dirOutput = dir(fullfile(fileFolder, '*.mat'));
fileNames={dirOutput.name}; % 1*100 cell
numFile = length(fileNames);
for idxFile = 1:numFile
path = [root fileNames{idxFile}];
matfile = load(path);
OPE_matfile = matfile.results{1};
bbox = OPE_matfile.res;
seq_name = fileNames{idxFile}(1:end-13);
sprintf(['now trans ' seq_name ' from mat to txt'])
dlmwrite([dst seq_name '.txt'],bbox,'precision','%.4f');
end
具体评价方法在论文中有介绍: