目标检测查全率和查准率Python代码实现
查准率和查全率计算
一堆照片,其中有12张是狗,其余是猫。算法识别出8只狗。在确定的8只狗中,有5只实际上真的是狗(真阳新TP),其余的是猫(假阳性FP),则精度为5/8,召回率为5/12。
实现
代码主要参考https://github.com/ZhouJiaHuan
import numpy as np
import os
import matplotlib.pyplot as plt
#计算交并比
def compute_iou(box1, box2, wh=False):
"""
compute the iou of two boxes.
Args:
box1, box2: [xmin, ymin, xmax, ymax] (wh=False) or [xcenter, ycenter, w, h] (wh=True)
wh: the format of coordinate.
Return:
iou: iou of box1 and box2.
"""
if wh == False:
xmin1, ymin1, xmax1, ymax1 = box1
xmin2, ymin2, xmax2, ymax2 = box2
else:
xmin1, ymin1 = int(box1[0]-box1[2]/2.0), int(box1[1]-box1[3]/2.0)
xmax1, ymax1 = int(box1[0]+box1[2]/2.0), int(box1[1]+box1[3]/2.0)
xmin2, ymin2 = int(box2[0]-box2[2]/2.0), int(box2[1]-box2[3]/2.0)
xmax2, ymax2 = int(box2[0]+box2[2]/2.0), int(box2[1]+box2[3]/2.0)
xx1 = np.max([xmin1, xmin2])
yy1 = np.max([ymin1, ymin2])
xx2 = np.min([xmax1, xmax2])
yy2 = np.min([ymax1, ymax2])
area1 = (xmax1-xmin1) * (ymax1-ymin1)
area2 = (xmax2-xmin2) * (ymax2-ymin2)
inter_area = (np.max([0, xx2-xx1])) * (np.max([0, yy2-yy1]))
iou = inter_area / (area1+area2-inter_area+1e-6)
return iou
#把标记按{img:{img:[[x1, y1, x2, y2], [x1, y1, x2, y2], ...]}}的格式返回
def process_labels(label_txt):
""" process the prediction.
Args:
predict_txt: a txt file of prection result, one row data is
formated as "img_path x1 y1 x2 y2 cls x1 y1 x2 y2 cls ...\n"
Return:
predicts_dict: a prediction dict containing all the objects information of all test images.
{image1: {"obj1": [[x1, y1, x2, y2], [x1, y1, x2, y2], ...], "obj2": ...}
"""
predict_dict = {}
with open(label_txt, "r") as f:
predict = f.readlines()
for predict_row in predict:
img_dict = {}
predict_row = predict_row.rstrip()
predict_list = predict_row.split(" ")
img_name = os.path.split(predict_list[0])[-1]#os.path.split 按照路径将文件名和路径分割开
obj_info = predict_list[1:]
obj_info = [int(i) for i in obj_info]
predict_dict[img_name] = {}
obj_num = int((len(obj_info)/5))
img_dict[img_name] = []
for obj_index in range(obj_num):#每隔5个数添加坐标
x1 = obj_info[5*obj_index]
y1 = obj_info[5*obj_index + 1]
x2 = obj_info[5*obj_index + 2]
y2 = obj_info[5*obj_index + 3]
img_dict[img_name].append([x1,y1,x2,y2])
predict_dict[img_name] = img_dict
return predict_dict
def process_predicts(predict_txt):
""" process the prediction.
Args:
predict_txt: a txt file of prection result, one row data is
formated as "img_path x1 y1 x2 y2 cls x1 y1 x2 y2 cls ...\n"
Return:
predicts_dict: a prediction dict containing all the objects information of all test images.
{image1: {"obj1": [[x1, y1, x2, y2], [x1, y1, x2, y2], ...], "obj2": ...}
"""
predict_dict = {}
with open(predict_txt, "r") as f:
predict = f.readlines()
for predict_row in predict:
img_dict = {}
predict_row = predict_row.rstrip()
predict_list = predict_row.split(" ")
img_name = os.path.split(predict_list[0])[-1]
obj_info = predict_list[1:]
obj_info = [int(i) for i in obj_info]
predict_dict[img_name] = {}
obj_num = int((len(obj_info)/4))
img_dict[img_name] = []
for obj_index in range(obj_num):#检测部分还没有识别标签,每隔4个添加坐标
x1 = obj_info[4*obj_index]
y1 = obj_info[4*obj_index + 1]
x2 = obj_info[4*obj_index + 2]
y2 = obj_info[4*obj_index + 3]
img_dict[img_name].append([x1, y1, x2, y2])
predict_dict[img_name] = img_dict
return predict_dict
#计算查全率和查准率
def compute_precision_recall(label_txt, predict_txt, iou1=0.5):
"""compute the precision and recall.
Args:
label_txt: a label txt file of objection information, one row data is
formated as "img_path x1 y1 x2 y2 cls x1 y1 x2 y2 cls ...\n"
predict_txt: a prediction txt file, same with label txt.
Return:
pre_rec: precision and recall dict.
{cls_name1: [precision1, recall1], cls_name2: [precision2, recall2], ...}
"""
pre_rec = {}
tp_count = {}
img_num_per_cls = {}
img_num_predict = {}
pre_rec = [0.0, 0.0]
tp_count = 0.0
img_num_per_cls = 1e-3
img_num_predict = 1e-3
label_dict = process_labels(label_txt)
predict_dict = process_predicts(predict_txt)
for img_name, obj_label in label_dict.items():
if img_name in predict_dict.keys():
obj_predict = predict_dict[img_name]
for obj, coords in obj_predict.items():#统计检测出的目标
img_num_predict += len(coords)
for obj, coords in obj_label.items():#统计标记出实际的目标
img_num_per_cls += len(coords)
if obj in obj_predict.keys():
for coord1 in coords:
for coord2 in obj_predict[obj]:
if compute_iou(coord1, coord2)>=iou1:
tp_count +=1
pre_rec = [tp_count/img_num_predict, tp_count/img_num_per_cls]
return pre_rec
if __name__ == "__main__":
label_txt = "./data_label.txt"
predict_txt = "./data_pre.txt"
pre_rec = compute_precision_recall(label_txt, predict_txt)
print(pre_rec)
os.path.split()
按照路径将文件名和路径分割开
以 “PATH” 中最后一个 ‘/’ 作为分隔符,分隔后,将索引为0的视为目录(路径),将索引为1的视为文件名,如:
import os
os.path.split(‘C:/soft/python/test.py’)
(‘C:/soft/python’, ‘test.py’)
os.path.split(‘C:/soft/python/test’)
(‘C:/soft/python’, ‘test’)
os.path.split(‘C:/soft/python/’)
(‘C:/soft/python’, ‘’)