【工具代码】目标检测绘制评估曲线
程序员文章站
2022-06-21 14:49:29
...
draw.py
# -*- coding: UTF-8 -*-
from pr import *
clas= ['ignore', 'pedestrian', 'people', 'bicycle', 'car', 'van', 'truck', 'tricycle', 'awning_tricycle', 'bus', 'motor'] # 类别
prediction_file=["FRCNN.txt", 'RetinaNet.txt', 'ourResult.txt', 'SSD.txt', "CenterNet.txt"] # 放在Prediction里面"Faster_RCNN.txt"
prediction_algorithm=["FRCNN", 'RetinaNet', 'ourResult', 'SSD', "CenterNet"] # 对应上面的文件的算法名称
use_07_metric=[False, False, False, False, False]
ground_truth_file=["gt.txt", 'gt.txt', 'gt.txt', 'gt.txt', "gt.txt"] # 放在Ground Truth里面
# 绘制出了各个类别的Precision-Recall曲线
draw_pr(prediction_file,prediction_algorithm,ground_truth_file,clas,use_07_metric)
pr.py
# -*- coding: UTF-8 -*-
import numpy as np
import math
import matplotlib.pyplot as plt
def get_pr_data_map(prediction_file,ground_truth_file,cls_name,use_07_metric,ovthresh=0.5):
with open(ground_truth_file, 'r') as f:####读取各个算法的gt.txt文件
lines_gt = f.readlines() #gt.txt的每一行,line_gt为一维数组
with open(prediction_file, 'r') as f:####读取各个算法的pre.txt文件
lines_pre = f.readlines() #读取pre.txt的每一行,lines_gt为一维数组
#根据txt文件中每一行的空格进行划分,splitlines_gt为二维数组,行为每一行的数据,列为每一行的数据划分
splitlines_gt = [x.strip().split(' ') for x in lines_gt]
#imagenames_gt为一维数组,当第二列的类别与遍历的类别数相同时,将第一列加入到imagenames_gt中
imagenames_gt = [ x[0] for x in splitlines_gt ]
class_recs = {}
# #BB_gt为二维数组,当第二列的类别与遍历的类别数相同时,将第二列之后的加入到BB_gt中
BB_gt=np.array([[math.ceil(float(z)) for z in x[2:]] for x in splitlines_gt])
for i in range(len(imagenames_gt)):
#如果类别中没有该遍历的类别,则更新
if imagenames_gt[i] not in class_recs:
class_recs.update({imagenames_gt[i]:{"bbox":[],"det":[],"difficult":[]}})
#否则将BB_gt[i]插入到类别框信息中
class_recs[imagenames_gt[i]]["bbox"].append(BB_gt[i])
class_recs[imagenames_gt[i]]["det"].append(False)
class_recs[imagenames_gt[i]]["difficult"].append(False)
#npos为imagenames_gt的长度
npos=len(imagenames_gt)
splitlines_pre = [x.strip().split(' ') for x in lines_pre]
#image_ids为一维数组,当第二列的类别与遍历的类别数相同时,将第一列加入到image_ids中
image_ids = [x[0] for x in splitlines_pre]
#提取该类别预测框的置信度,当第二列的类别与遍历的类别数相同时,将第三列加入到confidence中
confidence = np.array([float(x[2]) for x in splitlines_pre])
#提取该类别预测框的bounging-boxes(二维数组),当第二列的类别与遍历的类别数相同时,将第三列之后的BBOX坐标插入
BB_pre = np.array([[float(z) for z in x[3:]] for x in splitlines_pre])
#按置信度大小将其索引从小到大排序(生成有顺序的一维数组)
sorted_ind = np.argsort(-confidence)
#按置信度大小将置信度从小到大排序(生成有顺序的一维数组)
sorted_scores = np.sort(-confidence)
#根据索引排序相应的bbox的坐标值(生成按置信度大小排列的二维数组)
BB_pre = BB_pre[sorted_ind, :]
#按置信度大小重新排列image_ids
image_ids = [image_ids[x] for x in sorted_ind]
nd = len(image_ids)
tp = np.zeros(nd)
fp = np.zeros(nd)
pr_data_map=[]
for d in range(nd):
if class_recs.get(image_ids[d]):
#print(image_ids[d])
R = class_recs[image_ids[d]]
#print(R)
bb = np.array(BB_pre[d, :]).astype(float)#按置信度顺序提取bounding box
ovmax = -np.inf#ovmax为负无穷大的数
BBGT = np.array(R['bbox']).astype(float)#按置信度顺序提取groudtruth bbox
#计算iou
if BBGT.size > 0:
ixmin = np.maximum(BBGT[:, 0], bb[0])
iymin = np.maximum(BBGT[:, 1], bb[1])
ixmax = np.minimum(BBGT[:, 2], bb[2])
iymax = np.minimum(BBGT[:, 3], bb[3])
iw = np.maximum(ixmax - ixmin + 1., 0.)
ih = np.maximum(iymax - iymin + 1., 0.)
inters = iw * ih
uni = ((bb[2] - bb[0] + 1.) * (bb[3] - bb[1] + 1.) +
(BBGT[:, 2] - BBGT[:, 0] + 1.) *
(BBGT[:, 3] - BBGT[:, 1] + 1.) - inters)
overlaps = inters / uni#重叠率
ovmax = np.max(overlaps)#按重叠率的大小从大到小排序重叠率
jmax = np.argmax(overlaps)#根据重叠率大小重新排序的索引
if ovmax > ovthresh:#ovthresh=0.5阈值为0.5,判断tp和fp
if not R['difficult'][jmax]:
if not R['det'][jmax]:
tp[d] = 1.
R['det'][jmax] = 1
else:
fp[d] = 1.
else:
fp[d] = 1.
else:
fp[d]=1.
fp = np.cumsum(fp)
tp = np.cumsum(tp)
#rec=tp/正样本数
rec = tp / float(npos)
print(len(rec))
# print(type(rec))
#perc=tp/(tp+fp)
prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
print(len(prec))
# print(type(prec))
ap = voc_ap(rec, prec, use_07_metric)
print(ap)
pr_data_map=np.array([rec.tolist(),prec.tolist()])#,ap.tolist()]
pr_data_map=pr_data_map.tolist()
#print(pr_data_map)
return pr_data_map
def get_pr_data(prediction_file,ground_truth_file,cls_name,use_07_metric,ovthresh=0.5):
with open(ground_truth_file, 'r') as f:####读取各个算法的gt.txt文件
lines_gt = f.readlines() #gt.txt的每一行,line_gt为一维数组
with open(prediction_file, 'r') as f:####读取各个算法的pre.txt文件
lines_pre = f.readlines() #读取pre.txt的每一行,lines_gt为一维数组
pr_data={}
for cls_num in range(len(cls_name)): #遍历每个类别数
# print(cls_num)
#ground_truth
#根据txt文件中每一行的空格进行划分,splitlines_gt为二维数组,行为每一行的数据,列为每一行的数据划分
splitlines_gt = [x.strip().split(' ') for x in lines_gt]
#imagenames_gt为一维数组,当第二列的类别与遍历的类别数相同时,将第一列加入到imagenames_gt中
imagenames_gt = [ x[0] for x in splitlines_gt if int(x[1])==cls_num]
#print(imagenames_gt)
#BB_gt为二维数组,当第二列的类别与遍历的类别数相同时,将第二列之后的加入到BB_gt中
BB_gt=np.array([[math.ceil(float(z)) for z in x[2:]] for x in splitlines_gt if int(x[1])==cls_num])
#创建class_recs数组
class_recs = {}
for i in range(len(imagenames_gt)):
#如果类别中没有该遍历的类别,则更新
if imagenames_gt[i] not in class_recs:
class_recs.update({imagenames_gt[i]:{"bbox":[],"det":[],"difficult":[]}})
#否则将BB_gt[i]插入到类别框信息中
class_recs[imagenames_gt[i]]["bbox"].append(BB_gt[i])
class_recs[imagenames_gt[i]]["det"].append(False)
class_recs[imagenames_gt[i]]["difficult"].append(False)
#print(class_recs[imagenames_gt[i]])
#npos为imagenames_gt的长度
npos=len(imagenames_gt)
#prediction
#对预测框的每一行根据空格划分,splitlines_pre为二维数组
splitlines_pre = [x.strip().split(' ') for x in lines_pre]
#image_ids为一维数组,当第二列的类别与遍历的类别数相同时,将第一列加入到image_ids中
image_ids = [x[0] for x in splitlines_pre if int(x[1])==cls_num]
#提取该类别预测框的置信度,当第二列的类别与遍历的类别数相同时,将第三列加入到confidence中
confidence = np.array([float(x[2]) for x in splitlines_pre if int(x[1])==cls_num])
#提取该类别预测框的bounging-boxes(二维数组),当第二列的类别与遍历的类别数相同时,将第三列之后的BBOX坐标插入
BB_pre = np.array([[float(z) for z in x[3:]] for x in splitlines_pre if int(x[1])==cls_num])
#按置信度大小将其索引从小到大排序(生成有顺序的一维数组)
sorted_ind = np.argsort(-confidence)
#按置信度大小将置信度从小到大排序(生成有顺序的一维数组)
sorted_scores = np.sort(-confidence)
#根据索引排序相应的bbox的坐标值(生成按置信度大小排列的二维数组)
BB_pre = BB_pre[sorted_ind, :]
#按置信度大小重新排列image_ids
image_ids = [image_ids[x] for x in sorted_ind]
#该类别的预测框的数量
nd = len(image_ids)
tp = np.zeros(nd)#将长度为nd数组置0
fp = np.zeros(nd)
# print(nd)###############################################################################################################
for d in range(nd):
#按置信度顺序提取类别框
#print(image_ids[d].get(image_ids[d]))
# if class_recs[image_ids[d]] not in class_recs:
if class_recs.get(image_ids[d]):
#print(image_ids[d])
R = class_recs[image_ids[d]]
#print(R)
bb = np.array(BB_pre[d, :]).astype(float)#按置信度顺序提取bounding box
ovmax = -np.inf#ovmax为负无穷大的数
BBGT = np.array(R['bbox']).astype(float)#按置信度顺序提取groudtruth bbox
#计算iou
if BBGT.size > 0:
ixmin = np.maximum(BBGT[:, 0], bb[0])
iymin = np.maximum(BBGT[:, 1], bb[1])
ixmax = np.minimum(BBGT[:, 2], bb[2])
iymax = np.minimum(BBGT[:, 3], bb[3])
iw = np.maximum(ixmax - ixmin + 1., 0.)
ih = np.maximum(iymax - iymin + 1., 0.)
inters = iw * ih
uni = ((bb[2] - bb[0] + 1.) * (bb[3] - bb[1] + 1.) +
(BBGT[:, 2] - BBGT[:, 0] + 1.) *
(BBGT[:, 3] - BBGT[:, 1] + 1.) - inters)
overlaps = inters / uni#重叠率
ovmax = np.max(overlaps)#按重叠率的大小从大到小排序重叠率
jmax = np.argmax(overlaps)#根据重叠率大小重新排序的索引
if ovmax > ovthresh:#ovthresh=0.5阈值为0.5,判断tp和fp
if not R['difficult'][jmax]:
if not R['det'][jmax]:
tp[d] = 1.
R['det'][jmax] = 1
else:
fp[d] = 1.
else:
fp[d] = 1.
else:
#print("*************************************************************"+str(d))
fp[d]=1.
fp = np.cumsum(fp)
tp = np.cumsum(tp)
#rec=tp/正样本数
rec = tp / float(npos)
#print(rec)
# print(type(rec))
#perc=tp/(tp+fp)
prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
#?print(prec)
# print(type(prec))
ap = voc_ap(rec, prec, use_07_metric)
#print(ap)
if cls_name[cls_num] not in pr_data:
pr_data.update({cls_name[cls_num]:[rec,prec,ap]})
return pr_data #,mAP/7,np.array(mAP_rec/7),np.array(mAP_prec/7)
def voc_ap(rec, prec, use_07_metric):#由于use_07_metric=true时计算结果于实际更接近
#计算ap,use_07_metric=true,# 2010年以前按recall等间隔取11个不同点处的精度值做平均(0., 0.1, 0.2, …, 0.9, 1.0)
if use_07_metric:
ap = 0.
for t in np.arange(0., 1.1, 0.1):#([0.0,0.1,0.2,0.3,...,1.0])
#print(11111111111111111111111111)
if np.sum(rec >= t) == 0:
p = 0
else:
p = np.max(prec[rec >= t])
ap = ap + p / 11.
#use_07_metric=false # 2010年以后取所有不同的recall对应的点处的精度值做平均
else:
mrec = np.concatenate(([0.], rec, [1.]))
mpre = np.concatenate(([0.], prec, [0.]))
for i in range(mpre.size - 1, 0, -1):
mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])
i = np.where(mrec[1:] != mrec[:-1])[0]
ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
return ap
def draw_pr(prediction_file,prediction_algorithm,ground_truth_file,cls,use_07_metric):
#画多个算法多个类别的pr曲线
MAP=[0, 0, 0, 0, 0, 0, 0]#用于统计map
COLOR = ["#054E9F", "#FFA500", "#B0C4DE", "#008000", "#f6aad0", "#429ffd", "#435055"]
for cls_name in cls:
for i in range(len(prediction_file)):
pr_data=get_pr_data("Prediction/"+prediction_file[i],"Ground_Truth/"+ground_truth_file[i],cls,use_07_metric[i])
MAP[i]=MAP[i]+pr_data[cls_name][2]
the_color = COLOR[i]
plt.plot(pr_data[cls_name][0],pr_data[cls_name][1],label=prediction_algorithm[i],color=the_color)
title=cls_name+' PR Curve'
plt.title(title)
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.ylim([0.0, 1.0])
plt.xlim([0.0, 1.0])
plt.grid(ls='-.')
plt.legend()
plt.savefig("Image_PR/"+title+'.png', dpi=600)
# plt.show()
plt.close()
#画各个算法map的pr曲线
for i in range(len(prediction_file)):
pr_data_map=get_pr_data_map("Prediction/"+prediction_file[i],"Ground_Truth/"+ground_truth_file[i],cls,use_07_metric[i])
the_color = COLOR[i]
plt.plot(pr_data_map[0],pr_data_map[1],label=prediction_algorithm[i],color=the_color)
title='Precision-Recall Curve'
plt.title(title)
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.ylim([0.0, 1.0])
plt.xlim([0.0, 1.0])
plt.grid(ls='-.')
plt.legend()
plt.savefig("Image_PR/"+title+'.png', dpi=600)
plt.show()
plt.close()
# if __name__ == '__main__':
# # -*- coding: UTF-8 -*-
# import matplotlib.pyplot as plt
# cls=['pedestrian', 'people', 'bicycle', 'car', 'van', 'truck', 'tricycle', 'awning_tricycle', 'bus', 'motor'] # 类别
# # prediction_file=["FRCNN.txt", 'RetinaNet.txt', 'CornerNet.txt', 'CenterNet.txt', 'tridentnet.txt', 'ourResult.txt', 'SSD.txt'] # 放在Prediction里面"Faster_RCNN.txt",记得新建文件夹Prediction
# # prediction_algorithm=["FRCNN", 'RetinaNet', 'CornerNet', 'CenterNet', 'tridentnet', 'ourResult', 'SSD'] # 对应上面的文件的算法名称
# # use_07_metric=[False, False, False, False, False, False, False]
# # ground_truth_file=["gt.txt", 'gt.txt', 'gt.txt', 'gt.txt', 'gt.txt', 'gt.txt', 'gt.txt']# 放在Ground Truth里面,记得新建文件夹Ground Truth
# prediction_file=["FRCNN.txt", 'RetinaNet.txt', 'ourResult.txt', 'SSD.txt'] # 放在Prediction里面"Faster_RCNN.txt",记得新建文件夹Prediction
# prediction_algorithm=["FRCNN", 'RetinaNet', 'ourResult', 'SSD'] # 对应上面的文件的算法名称
# use_07_metric=[False, False, False, False]
# ground_truth_file=["gt.txt", 'gt.txt', 'gt.txt', 'gt.txt']# 放在Ground Truth里面,记得新建文件夹Ground Truth
# # 绘制出了各个类别的Precision-Recall曲线
# draw_pr(prediction_file,prediction_algorithm,ground_truth_file,cls,use_07_metric)
froc.py
# -*- coding: UTF-8 -*-
#以faster和yolo为例
import numpy as np
import math
import matplotlib.pyplot as plt
def get_pr_data_map(prediction_file,ground_truth_file,cls_name,use_07_metric,ovthresh=0.5):
with open(ground_truth_file, 'r') as f:####读取各个算法的gt.txt文件
lines_gt = f.readlines() #gt.txt的每一行,line_gt为一维数组
with open(prediction_file, 'r') as f:####读取各个算法的pre.txt文件
lines_pre = f.readlines() #读取pre.txt的每一行,lines_gt为一维数组
#根据txt文件中每一行的空格进行划分,splitlines_gt为二维数组,行为每一行的数据,列为每一行的数据划分
splitlines_gt = [x.strip().split(' ') for x in lines_gt]
#imagenames_gt为一维数组,当第二列的类别与遍历的类别数相同时,将第一列加入到imagenames_gt中
imagenames_gt = [ x[0] for x in splitlines_gt ]
#print(imagenames_gt)
class_recs = {}
# #BB_gt为二维数组,当第二列的类别与遍历的类别数相同时,将第二列之后的加入到BB_gt中
BB_gt=np.array([[math.ceil(float(z)) for z in x[2:]] for x in splitlines_gt])
for i in range(len(imagenames_gt)):
#如果类别中没有该遍历的类别,则更新
if imagenames_gt[i] not in class_recs:
class_recs.update({imagenames_gt[i]:{"bbox":[],"det":[],"difficult":[]}})
#否则将BB_gt[i]插入到类别框信息中
class_recs[imagenames_gt[i]]["bbox"].append(BB_gt[i])
class_recs[imagenames_gt[i]]["det"].append(False)
class_recs[imagenames_gt[i]]["difficult"].append(False)
#npos为imagenames_gt的长度
npos=len(imagenames_gt)
splitlines_pre = [x.strip().split(' ') for x in lines_pre]
#image_ids为一维数组,当第二列的类别与遍历的类别数相同时,将第一列加入到image_ids中
image_ids = [x[0] for x in splitlines_pre]
#提取该类别预测框的置信度,当第二列的类别与遍历的类别数相同时,将第三列加入到confidence中
confidence = np.array([float(x[2]) for x in splitlines_pre])
#提取该类别预测框的bounging-boxes(二维数组),当第二列的类别与遍历的类别数相同时,将第三列之后的BBOX坐标插入
BB_pre = np.array([[float(z) for z in x[3:]] for x in splitlines_pre])
#按置信度大小将其索引从小到大排序(生成有顺序的一维数组)
sorted_ind = np.argsort(-confidence)
#按置信度大小将置信度从小到大排序(生成有顺序的一维数组)
sorted_scores = np.sort(-confidence)
#根据索引排序相应的bbox的坐标值(生成按置信度大小排列的二维数组)
BB_pre = BB_pre[sorted_ind, :]
#按置信度大小重新排列image_ids
image_ids = [image_ids[x] for x in sorted_ind]
nd = len(image_ids)
tp = np.zeros(nd)
fp = np.zeros(nd)
pr_data_map=[]
# print(nd)###############################################################################################################
for d in range(nd):
#按置信度顺序提取类别框
#print(image_ids[d].get(image_ids[d]))
# if class_recs[image_ids[d]] not in class_recs:
# print(class_recs)
if class_recs.get(image_ids[d]):
#print(image_ids[d])
R = class_recs[image_ids[d]]
#print(R)
bb = np.array(BB_pre[d, :]).astype(float)#按置信度顺序提取bounding box
ovmax = -np.inf#ovmax为负无穷大的数
BBGT = np.array(R['bbox']).astype(float)#按置信度顺序提取groudtruth bbox
#计算iou
if BBGT.size > 0:
ixmin = np.maximum(BBGT[:, 0], bb[0])
iymin = np.maximum(BBGT[:, 1], bb[1])
ixmax = np.minimum(BBGT[:, 2], bb[2])
iymax = np.minimum(BBGT[:, 3], bb[3])
iw = np.maximum(ixmax - ixmin + 1., 0.)
ih = np.maximum(iymax - iymin + 1., 0.)
inters = iw * ih
uni = ((bb[2] - bb[0] + 1.) * (bb[3] - bb[1] + 1.) +
(BBGT[:, 2] - BBGT[:, 0] + 1.) *
(BBGT[:, 3] - BBGT[:, 1] + 1.) - inters)
overlaps = inters / uni#重叠率
ovmax = np.max(overlaps)#按重叠率的大小从大到小排序重叠率
jmax = np.argmax(overlaps)#根据重叠率大小重新排序的索引
if ovmax > ovthresh:#ovthresh=0.5阈值为0.5,判断tp和fp
if not R['difficult'][jmax]:
if not R['det'][jmax]:
tp[d] = 1.
R['det'][jmax] = 1
else:
fp[d] = 1.
else:
fp[d] = 1.
else:
#print("*************************************************************"+str(d))
fp[d]=1.
fp = np.cumsum(fp)
tp = np.cumsum(tp)
#rec=tp/正样本数
rec = tp / float(npos)
# print(len(rec))
# print(type(rec))
#perc=tp/(tp+fp)
prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
# print(len(prec))
fps = fp / npos
# print(fps, prec, nd)
# print(type(prec))
ap = voc_ap(rec, prec, use_07_metric)
print(ap)
###################################################
# mAP_rec+=rec
# print("mAP_rec:"+str(mAP_rec)+"\n")
# mAP_prec+=prec
# print("mAP_prec:"+str(mAP_prec)+"\n")
# mAP+=ap
# print("mAP:"+str(mAP)+"\n")
###################################################
# if not pr_data.has_key(cls_name[cls_num]):
# rec=np.array(rec)
# prec=np.array(prec)
# ap=np.array(ap)
pr_data_map=np.array([fps.tolist(), rec.tolist()])#,ap.tolist()]
pr_data_map=pr_data_map.tolist()
#print(pr_data_map)
return pr_data_map
def get_pr_data(prediction_file,ground_truth_file,cls_name,use_07_metric,ovthresh=0.5):
with open(ground_truth_file, 'r') as f:####读取各个算法的gt.txt文件
lines_gt = f.readlines() #gt.txt的每一行,line_gt为一维数组
with open(prediction_file, 'r') as f:####读取各个算法的pre.txt文件
lines_pre = f.readlines() #读取pre.txt的每一行,lines_gt为一维数组
pr_data={}
for cls_num in range(len(cls_name)): #遍历每个类别数
#ground_truth
#根据txt文件中每一行的空格进行划分,splitlines_gt为二维数组,行为每一行的数据,列为每一行的数据划分
splitlines_gt = [x.strip().split(' ') for x in lines_gt]
#imagenames_gt为一维数组,当第二列的类别与遍历的类别数相同时,将第一列加入到imagenames_gt中
imagenames_gt = [ x[0] for x in splitlines_gt if int(x[1])==cls_num]
#print(imagenames_gt)
#BB_gt为二维数组,当第二列的类别与遍历的类别数相同时,将第二列之后的加入到BB_gt中
BB_gt=np.array([[math.ceil(float(z)) for z in x[2:]] for x in splitlines_gt if int(x[1])==cls_num])
#创建class_recs数组
class_recs = {}
for i in range(len(imagenames_gt)):
#如果类别中没有该遍历的类别,则更新
if imagenames_gt[i] not in class_recs:
class_recs.update({imagenames_gt[i]:{"bbox":[],"det":[],"difficult":[]}})
#否则将BB_gt[i]插入到类别框信息中
class_recs[imagenames_gt[i]]["bbox"].append(BB_gt[i])
class_recs[imagenames_gt[i]]["det"].append(False)
class_recs[imagenames_gt[i]]["difficult"].append(False)
#print(class_recs[imagenames_gt[i]])
#npos为imagenames_gt的长度
npos=len(imagenames_gt)
#prediction
#对预测框的每一行根据空格划分,splitlines_pre为二维数组
splitlines_pre = [x.strip().split(' ') for x in lines_pre]
#image_ids为一维数组,当第二列的类别与遍历的类别数相同时,将第一列加入到image_ids中
image_ids = [x[0] for x in splitlines_pre if int(x[1])==cls_num]
#提取该类别预测框的置信度,当第二列的类别与遍历的类别数相同时,将第三列加入到confidence中
confidence = np.array([float(x[2]) for x in splitlines_pre if int(x[1])==cls_num])
#提取该类别预测框的bounging-boxes(二维数组),当第二列的类别与遍历的类别数相同时,将第三列之后的BBOX坐标插入
BB_pre = np.array([[float(z) for z in x[3:]] for x in splitlines_pre if int(x[1])==cls_num])
#按置信度大小将其索引从小到大排序(生成有顺序的一维数组)
sorted_ind = np.argsort(-confidence)
#按置信度大小将置信度从小到大排序(生成有顺序的一维数组)
sorted_scores = np.sort(-confidence)
#根据索引排序相应的bbox的坐标值(生成按置信度大小排列的二维数组)
BB_pre = BB_pre[sorted_ind, :]
#按置信度大小重新排列image_ids
image_ids = [image_ids[x] for x in sorted_ind]
#该类别的预测框的数量
nd = len(image_ids)
tp = np.zeros(nd)#将长度为nd数组置0
fp = np.zeros(nd)
# print(nd)###############################################################################################################
for d in range(nd):
#按置信度顺序提取类别框
#print(image_ids[d].get(image_ids[d]))
# if class_recs[image_ids[d]] not in class_recs:
if class_recs.get(image_ids[d]):
#print(image_ids[d])
R = class_recs[image_ids[d]]
#print(R)
bb = np.array(BB_pre[d, :]).astype(float)#按置信度顺序提取bounding box
ovmax = -np.inf#ovmax为负无穷大的数
BBGT = np.array(R['bbox']).astype(float)#按置信度顺序提取groudtruth bbox
#计算iou
if BBGT.size > 0:
ixmin = np.maximum(BBGT[:, 0], bb[0])
iymin = np.maximum(BBGT[:, 1], bb[1])
ixmax = np.minimum(BBGT[:, 2], bb[2])
iymax = np.minimum(BBGT[:, 3], bb[3])
iw = np.maximum(ixmax - ixmin + 1., 0.)
ih = np.maximum(iymax - iymin + 1., 0.)
inters = iw * ih
uni = ((bb[2] - bb[0] + 1.) * (bb[3] - bb[1] + 1.) +
(BBGT[:, 2] - BBGT[:, 0] + 1.) *
(BBGT[:, 3] - BBGT[:, 1] + 1.) - inters)
overlaps = inters / uni#重叠率
ovmax = np.max(overlaps)#按重叠率的大小从大到小排序重叠率
jmax = np.argmax(overlaps)#根据重叠率大小重新排序的索引
if ovmax > ovthresh:#ovthresh=0.5阈值为0.5,判断tp和fp
if not R['difficult'][jmax]:
if not R['det'][jmax]:
tp[d] = 1.
R['det'][jmax] = 1
else:
fp[d] = 1.
else:
fp[d] = 1.
else:
#print("*************************************************************"+str(d))
fp[d]=1.
fp = np.cumsum(fp)
tp = np.cumsum(tp)
#rec=tp/正样本数
rec = tp / float(npos)
#print(rec)
# print(type(rec))
#perc=tp/(tp+fp)
prec = tp / np.maximum(tp + fp, np.finfo(np.float64).eps)
#?print(prec)
# print(type(prec))
ap = voc_ap(rec, prec, use_07_metric)
#print(ap)
###################################################
fps = fp / npos
# mAP_rec+=rec
# print("mAP_rec:"+str(mAP_rec)+"\n")
# mAP_prec+=prec
# print("mAP_prec:"+str(mAP_prec)+"\n")
# mAP+=ap
# print("mAP:"+str(mAP)+"\n")
###################################################
if cls_name[cls_num] not in pr_data:
pr_data.update({cls_name[cls_num]:[fps,rec,ap]})
return pr_data #,mAP/7,np.array(mAP_rec/7),np.array(mAP_prec/7)
def voc_ap(rec, prec, use_07_metric):#由于use_07_metric=true时计算结果于实际更接近
#计算ap,use_07_metric=true,# 2010年以前按recall等间隔取11个不同点处的精度值做平均(0., 0.1, 0.2, …, 0.9, 1.0)
if use_07_metric:
ap = 0.
for t in np.arange(0., 1.1, 0.1):#([0.0,0.1,0.2,0.3,...,1.0])
#print(11111111111111111111111111)
if np.sum(rec >= t) == 0:
p = 0
else:
p = np.max(prec[rec >= t])
ap = ap + p / 11.
#use_07_metric=false # 2010年以后取所有不同的recall对应的点处的精度值做平均
else:
mrec = np.concatenate(([0.], rec, [1.]))
mpre = np.concatenate(([0.], prec, [0.]))
for i in range(mpre.size - 1, 0, -1):
mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])
i = np.where(mrec[1:] != mrec[:-1])[0]
ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
return ap
def draw_pr(prediction_file,prediction_algorithm,ground_truth_file,cls,use_07_metric):
# for i in range(len(prediction_file)):
# pr_data=get_pr_data("Prediction/"+prediction_file[i],"Ground_Truth/"+ground_truth_file,cls)
# for cls_name in pr_data:
# plt.plot(pr_data[cls_name][0],pr_data[cls_name][1],label=prediction_algorithm[i]+' mAP='+str(round(pr_data[cls_name][2],3)))
# title='PR Curve of '+cls_name
# plt.title(title)
# plt.xlabel('Recall')
# plt.ylabel('Precision')
# plt.ylim([0.0, 1.0])
# plt.xlim([0.0, 1.0])
# plt.grid(ls='-.')
# plt.legend()
# plt.savefig("Images/"+title+'.png', dpi=300)
# plt.show()
# plt.close()
# for i in range(len(prediction_file)):
# pr_data=get_pr_data("Prediction/"+prediction_file[i],"Ground_Truth/"+ground_truth_file,cls)
#画多个算法多个类别的pr曲线
MAP=[0,0,0,0,0,0]#用于统计map
for cls_name in cls:
for i in range(len(prediction_file)):
pr_data=get_pr_data("Prediction/"+prediction_file[i],"Ground_Truth/"+ground_truth_file[i],cls,use_07_metric[i])
MAP[i]=MAP[i]+pr_data[cls_name][2]
# print(pr_data)
if i==0:
plt.plot(pr_data[cls_name][0],pr_data[cls_name][1],label=prediction_algorithm[i]+' AP='+str(round(pr_data[cls_name][2],3)),color="#054E9F")
elif i==1:
plt.plot(pr_data[cls_name][0],pr_data[cls_name][1],label=prediction_algorithm[i]+' AP='+str(round(pr_data[cls_name][2],3)),color="#FFA500")
elif i==2:
plt.plot(pr_data[cls_name][0],pr_data[cls_name][1],label=prediction_algorithm[i]+' AP='+str(round(pr_data[cls_name][2],3)),color="#B0C4DE")
elif i==3:
plt.plot(pr_data[cls_name][0],pr_data[cls_name][1],label=prediction_algorithm[i]+' AP='+str(round(pr_data[cls_name][2],3)),color="#008000")
elif i==4:
plt.plot(pr_data[cls_name][0],pr_data[cls_name][1],label=prediction_algorithm[i]+' AP='+str(round(pr_data[cls_name][2],3)),color="#BA55D3")
elif i==5:
plt.plot(pr_data[cls_name][0],pr_data[cls_name][1],label=prediction_algorithm[i]+' AP='+str(round(pr_data[cls_name][2],3)),color="#FF0000")
# plt.plot(pr_data[cls_name][0],pr_data[cls_name][1],label=prediction_algorithm[i]+' AP='+str(round(pr_data[cls_name][2],3)),color="#054E9F")
title=cls_name+' FROC Curve'
plt.title(title,fontsize=15)
plt.xlabel('False Positive Per Scan',fontsize=15)
plt.ylabel('Sensitive',fontsize=15)
plt.ylim([0.0, 1.0])
plt.xlim([0.0, 10])
plt.grid(ls='-.')
plt.legend()
plt.savefig("Image_PR/"+title+'.png', dpi=600)
print("save....ok!!!")
plt.show()
plt.close()
#画各个算法map的pr曲线
for i in range(len(prediction_file)):
pr_data_map=get_pr_data_map("Prediction/"+prediction_file[i],"Ground_Truth/"+ground_truth_file[i],cls,use_07_metric[i])
if i==0:
plt.plot(pr_data_map[0],pr_data_map[1],label=prediction_algorithm[i]+' mAP='+str(round(MAP[i]/len(cls),3)),color="#054E9F")
elif i==1:
plt.plot(pr_data_map[0],pr_data_map[1],label=prediction_algorithm[i]+' mAP='+str(round(MAP[i]/len(cls),3)),color="#FFA500")
elif i==2:
plt.plot(pr_data_map[0],pr_data_map[1],label=prediction_algorithm[i]+' mAP='+str(round(MAP[i]/len(cls),3)),color="#B0C4DE")
elif i==3:
plt.plot(pr_data_map[0],pr_data_map[1],label=prediction_algorithm[i]+' mAP='+str(round(MAP[i]/len(cls),3)),color="#008000")
elif i==4:
plt.plot(pr_data_map[0],pr_data_map[1],label=prediction_algorithm[i]+' mAP='+str(round(MAP[i]/len(cls),3)),color="#BA55D3")
elif i==5:
plt.plot(pr_data_map[0],pr_data_map[1],label=prediction_algorithm[i]+' mAP='+str(round(MAP[i]/len(cls),3)),color="#FF0000")
#plt.plot(pr_data_map[0],pr_data_map[1],label=prediction_algorithm[i]+' mAP='+str(round(MAP[i]/len(cls),3)),color="#054E9F")
title='FROC Curve'
plt.title(title,fontsize=15)
plt.xlabel('False Positive Per Scan',fontsize=15)
plt.ylabel('Sensitive',fontsize=15)
plt.ylim([0.0, 1.0])
plt.xlim([0.0, 10])
plt.grid(ls='-.')
plt.legend()
plt.savefig("Image_PR/"+title+'.png', dpi=600)
print("save....ok!!!")
plt.show()
plt.close()