大家好,这是本小白的第一篇博客,主要是在作者"倔强的大萝卜"这篇文章 【YOLOV3-keras-MAP】YOLOV3-keras版本的mAP计算(https://blog.csdn.net/plSong_CSDN/article/details/89502117)的基础上,进行补充,最终实现自己数据集的keras-yolov3的mAP计算。前提是,已经训练好了h5文件。
原博主直接给出了代码包 https://github.com/Cartucho/mAP,其博客也有关键代码的解释,但并没有给出整个连续的实现过程,我看评论里也有一些同是小白的盆友求具体代码,我把它连贯起来了,在这里记录总结一下~
首先引用一下 目标检测问题中的-MAP 里的几个基本概念:
MAP(mean Average Precision):均值平均精度。目标检测模型的性能评估
Ground Truth:对于任何算法,度量总是与数据的真实值(Ground Truth)进行比较,Ground Truth就是数据的真实值。Ground Truth包括图像中的目标的类别以及图像中每个目标的边界框。
Iou:交并比。交并比是模型所预测的检测框和真实(Ground Truth)的检测框的交集和并集之间的比例。
如何计算可以查看原博主 目标检测问题中的-MAP 这篇博文,本文主要讲实现方法。
原博主给出了这个下载地址 mAP代码下载
下载后解压到keras-yolo3的主目录下,若要计算自己的数据,可以把压缩包里mAP-master/input下的三个文件夹(detection_results, ground_truth, images-optional)里的内容清空,以便后续放入自己的数据。
实现mAP的计算主要就是把相应的文件放入到 detection_results, ground_truth, images-optional 这三个文件夹中,然后根据压缩包里的main.py 文件直接生成结果。下面依次解释我是咋实现的。
先从最简单的开始吧,images-optional文件夹主要是放你要测试(test)的图像数据的。
第一种方法是,你只需要把你准备的测试图片粘进去
第二种方法是,你可以在main.py 文件中把IMG_PATH的路径引到你放测试图片的文件夹。下面是main.py 文件中的部分代码,修改即可。
GT_PATH = os.path.join(os.getcwd(), 'input', 'ground-truth')
DR_PATH = os.path.join(os.getcwd(), 'input', 'detection-results')
# if there are no images then no animation can be shown
# IMG_PATH = os.path.join(os.getcwd(), 'input', 'images-optional') 默认是images-optional
IMG_PATH = '/home/bu807/Downloads/keras-yolo3-master2/keras-yolo3-master2/test' #也可以引到自己的test路径
粘完图片,或者改完路径后,images-optional文件夹就搞定了。最简单。
ground_truth用来放真实值,就是你当初标的框的位置大小,如下:一张图里,眼睛 鼻子 嘴巴 的类型、位置和大小。
格式是:classname left top right bottom
eye 86 274 146 305
eye 214 273 282 303
nose 138 334 220 385
mouth 139 404 220 437
这里需要放入原始值的txt文件,我们可以根据xml文件生成。首先,需要将xml导入到ground_truth文件夹;然后,通过covert_gt_xml.py转成txt文件。
3.1 将xml导入到ground_truth文件夹
第一种方法,你的测试图片少的话,可以直接把相应的xml文件粘到ground_truth文件夹。
第二种方法,你的测试图片很多/一个一个找不好找,我简单写了一个代码(如下:findxml.py,你可以把它放在mAP-master/scripts/extra下 ),可以从你的Annotations文件夹中找到相应的xml文件,然后粘到ground_truth文件夹。
import os
import shutil
testfilepath='/home/bu807/Downloads/keras-yolo3-master2/keras-yolo3-master2/test'
xmlfilepath = '/home/bu807/Downloads/keras-yolo3-master2/keras-yolo3-master2/VOCdevkit/VOC2007/Annotations/'
xmlsavepath = '/home/bu807/Downloads/keras-yolo3-master2/keras-yolo3-master2/mAP-master/input/ground-truth/'
test_jpg = os.listdir(testfilepath)
num = len(test_jpg)
list = range(num)
L=[]
for i in list:
name = test_jpg[i][:-4] + '.xml'
L.append(name)
for filename in L:
shutil.copy(os.path.join(xmlfilepath,filename),xmlsavepath)
具体参考了
python: 从一个文件夹中提取含有特定文件名的文件并放到新文件夹中
(相对路径不太会写,就直接放的绝对路径了 /捂脸),这样就相应xml放进了ground_truth文件夹。
3.2 将xml转成txt文件
执行自带的mAP-master/scripts/extra/covert_gt_xml.py 文件。执行后,你的xml文件自动放进了ground_truth/backup中,然后在ground_truth下生成了txt文件。
OK,第二个文件夹搞定。
4.1 保存模型测试结果
采用原博主的这个 yolo_test.py 文件,可以实现批量测试 并 保存测试结果。( 博客见【yoloV3-keras】 keras-yolov3 进行批量测试 并 保存结果 )执行后会在主目录下生成result文件夹及下属文件。对其进行改进后,才能用于我们mAP的计算。我这里po出了我补充的代码,也是有盆友在问的:
1 )
注释掉两个file.write
# 保存框检测出的框的个数
# file.write('find ' + str(len(out_boxes)) + ' target(s) \n') 这里注释掉
time_sum = time.time() - t1
# file.write('time sum: ' + str(time_sum) + 's') 这里注释掉
print('time sum:', time_sum)
file.close()
yolo.close_session()
2 )
修改2个file.write
# 写入检测位置
# file.write(
# predicted_class + ' score: ' + str(score) + ' \nlocation: top: ' + str(top) + '、 bottom: ' + str(
# bottom) + '、 left: ' + str(left) + '、 right: ' + str(right) + '\n')
file.write(
predicted_class + ' ' + str(score) + ' ' + str(left) + ' ' + str(
top) + ' ' + str(right) + ' ' + str(bottom) + ';')
# file.write(portion[1] + ' detect_result:\n') 这个在最后
file.write(portion[1]+' ') # 这里要有一个空格
3 )
然后执行yolo_test.py,生成result/result.txt
4.2 执行py文件得到txt文件
这一步也是有些盆友在问的。我在scripts/extra下新建了make_dr.py 文件,如下:
f=open('/home/bu807/Downloads/keras-yolo3-master2/keras-yolo3-master2/result/result.txt',encoding='utf8')
s=f.readlines()
result_path='/home/bu807/Downloads/keras-yolo3-master2/keras-yolo3-master2/mAP-master/input/detection-results/'
for i in range(len(s)): # 中按行存放的检测内容,为列表的形式
r = s[i].split('.jpg ')
file = open(result_path + r[0] + '.txt', 'w')
if len(r[1]) > 5:
t = r[1].split(';')
# print('len(t):',len(t))
if len(t) == 3:
file.write(t[0] + '\n' + t[1] + '\n') # 有两个对象被检测出
elif len(t) == 4:
file.write(t[0] + '\n' + t[1] + '\n' + t[2] + '\n') # 有三个对象被检测出
elif len(t) == 5:
file.write(t[0] + '\n' + t[1] + '\n' + t[2] + '\n' + t[3] + '\n') # 有四个对象被检测出
elif len(t) == 6:
file.write(t[0] + '\n' + t[1] + '\n' + t[2] + '\n' + t[3] + '\n' + t[4] + '\n') # 有五个对象被检测出
elif len(t) == 7:
file.write(t[0] + '\n' + t[1] + '\n' + t[2] + '\n' + t[3] + '\n' + t[4] + '\n' + t[5] + '\n') # 有六个对象被检测出
else:
file.write(t[0] + '\n') # 有一个对象
else:
file.write('') # 没有检测出来对象,创建一个空白的对象
创建文件后执行,得到detection-results文件夹下的txt文件。
到这里,三个文件夹就搞定了!大功告成!
最后,执行 main.py 文件,在mAP-master/results下就可以看到自己的mAP啦!!!
有什么问题欢迎交流,本小白第一次写博客,如有侵权请提醒,我尽快处理或删除。