前言
基于自己数据集的模型训练出来后,就可以开始对测试图片(test.txt里面的文件名list,不带后缀)进行识别,然后计算出ap和map值。其实运行./experiment/scripts/faster_rcnn_end2end.sh,就可以在训练完后进行测试。但后来将测试图片进行了变更(即修改了test.txt内容),就只需要单独运行test_net.py来识别测试图片了。脚本运行命令如下图所示:
但是遇到了KeyError的问题,我这里没有把测试log贴出来。根本原因就是test.txt里面的文件名找不到,所以就报KeyError的错误。
代码分析
出错的代码在voc_eval.py的voc_eval()函数实现里面,如下图所示红框处。
出错log表示,recs[]这个dict(key:val结构)里面找不到某个test图片imagename这个key。 test图片的imagename显然是从更新的test.txt里面读出来的,这个显然没有问题。关键是recs的里面的keys和values值没有更新。
我们进一步trace代码,看recs是怎么获得的。同样在上面那个函数,分两个部分来讲解代码。
1)第一部分代码是读取annots.pkl作为cachfile,至于cachedir是哪个路径,打印出来是./data/VOCdevkit/annotations_cache
# first load gt
if not os.path.isdir(cachedir):
os.mkdir(cachedir)
cachefile = os.path.join(cachedir, 'annots.pkl')
2)第二部分代码则是讲这个cachefile存在否。如果不存在,则创建它,并把当前的test.txt里面所列imagename写到recs()里面,并保存到cachefile; 反之如果cachefile已经存在,那么就直接从这个cachefile里面读取。
if not os.path.isfile(cachefile):
# load annots
recs = {}
for i, imagename in enumerate(imagenames):
recs[imagename] = parse_rec(annopath.format(imagename))
if i % 100 == 0:
print 'Reading annotation for {:d}/{:d}'.format(
i + 1, len(imagenames))
# save
print 'Saving cached annotations to {:s}'.format(cachefile)
with open(cachefile, 'w') as f:
cPickle.dump(recs, f)
else:
# load
with open(cachefile, 'r') as f:
recs = cPickle.load(f)
解决办法
讲到这里,应该很清楚为什么test.txt内容更新,但是读出来的rects内容没有更新。 关键是cachefile内容没有更新,代码仍然从这个存在的cachefile里面读取。
所以最终解决办法也很简单,即直接先删除cachefile: rm -f data/VOCdevkit/annotations_cache/annots.pkl,然后再运行test_net.py就正确了。