本文只是将大家讲的计算mAP步骤总结一下,方便自己下次学习总结。
1.对测试集生成检测结果文件:
./darknet detector valid cfg/voc.data cfg/yolov3-voc.cfg backup/VOC/yolov3-voc_final.weights -out "" -gpu 0 -thresh .5
./darknet detector valid cfg/voc.data cfg/yolov3.cfg results/yolov3.weights -out [文件名] -thresh .5
./darknet detector valid <data_cfg> <test_cfg> <weights> <out_file>
注意:
- 文件名为 "" 就可以了,最后出来的是你的类别名,如:car、person等,有几类,就有几个 txt 文件
- <test_cfg>文件中 batch 和 subdivisions 两项必须为1。
- 结果生成在<data_cfg>的results指定的目录下以<out_file>开头的若干文件中,若<data_cfg>没有指定results,那么默认为<darknet_root>/results。
我现在跑的是红外行人数据集,只有一类:行人。下面是 person.txt 的内容:
每行是文件名,置信度,4个坐标。我的置信度挺高的,出来的 AP 值也很高。
2.下载voc_eval.py
https://github.com/rbgirshick/py-faster-rcnn/tree/master/lib/datasets
直接进去,新建 voc_eval.py 复制出来就好。注意,在voc_eval.py 中加入中文注释会报错,需要在第一行加入#coding=utf-8。
3.新建compute_mAP.py
from voc_eval import voc_eval
rec,prec,ap=voc_eval('/home/QHN/darknet/results/{}.txt', '/home/QHN/darknet/data/TEST/xml/{}.xml', '/home/QHN/darknet/data/TEST/TestImage.txt', 'airplane', '.')
print('rec',rec)
print('prec',prec)
print('ap',ap)
(1)参数解释(copy参考3):
第 1 项:存放检测结果文件的文件夹的路径(每个类别一个单独的文件,文件名可在valid命令时指定)+ { }.txt ;
第 2 项:存放xml标签文件的文件夹的路径 + { }.xml ;
第 3 项:测试集图片名称列表.txt文件的路径;注意:只是图片的名称,没后缀,没路径。
第 4 项:某类别对应的结果文件的名字(每次计算不同类别的AP,只需要更改此参数后重新运行脚本即可);
(2)原理解释(copy参考3):
首先通过第一项+第四项,选择本次要计算AP的类别对应的valid检测结果文件。
通过第三项的测试集图片名称列表遍历测试集中的每一张图片:对每一张图片而言,第一项+第四项+第三项可以匹配到属于本张图片的检测到的第四项所指类别物体的结果。
第二项+第三项可以匹配到当前图片的xml标签文件,进而在此xml文件中通过第四项匹配到对应类别的groundtruth。
最后eval.py通过对本图片中该类的GT标签和该类结果文件中属于本图片的检测结果的比对,完成对一张图片中某一类别的AP的计算,进而遍历完所有图片则完成对测试集的某一类别的AP计算。
(3)特别注意(copy参考3)!!!
①运行一次compute.py,就会在当前路径下生成一个annots.pkl文件,当更换数据集(包括同一数据集图片不变但xml文件改变)时,运行compute.py前,需要将之前生成的annots.pkl删掉,否则程序会沿用上一版的数据集(xml)进行计算,结果不准确。
②务必保证,"Valid结果文件中的图片种类"和“xml的个数”和"图片名称列表中条目数"一一对应 (这句话我没理解,我的xml个数就是像voc一样,都在annotation中,运行无错)。
③txt2xml.py中的输入图片size参数如何设置影响最终mAP值。
④valid命令最后的-thresh命令对测试结果无影响。
(4)第 3 项:测试集图片名称列表.txt文件的路径;注意:只是图片的名称,没后缀,没路径。
在我们训练时,我们生成了 train.txt 和 val.txt,他们中都是放着绝对路径。
f1 = open('/home/user/darknet/scripts/2018_val_1.txt','r')
f2 = open('/home/user/darknet/scripts/2018_val_2.txt','a')
while True:
text = f1.readline()
text1 = text.split('/')
text2 = text1[8]
text3 = text2.split('.')[0]
if not text:
break
print(text3)
f2.write(text3)
f2.write('\n')
f1.close()
f2.close()
2018_val_1.txt:放着绝对路径,如:/home/user/darknet/scripts/vocdevkit/voc2018/jpeimages/img_00017.bmp
2018_val_2.txt:保存处理后的路径
需要修改的地方:路径、两次分隔(第一次是'/',第二次是'.')
4.最后的结果
最后一行是 ap值。
遇到的问题:
1>keyerror:每次运行前记得删掉annots.pkl,不然会报错
2>找不到 person.txt ,看路径下明明有,然后就重命名了一下,重启命令行,ok了。
3>最恶心的是我在 voc_eval.py 加了中文注释,然后一直报错,我一直调 compute_map.py 。后来睡了一觉起来就看到问题了,看来调bug要养足精神,睁大眼睛,手动狗头。
参考1:https://blog.csdn.net/Gentleman_Qin/article/details/84800188
参考2:https://blog.csdn.net/mieleizhi0522/article/details/79989754
参考3:https://blog.csdn.net/Gentleman_Qin/article/details/84800188