您的当前位置:首页YOLOV5——计算预测数据的精确率(precision)和召回率(recall)

YOLOV5——计算预测数据的精确率(precision)和召回率(recall)

2024-01-23 来源:乌哈旅游
YOLOV5——计算预测数据的精确率(precision)和召回率

(recall)

1、预测数据

  使⽤ yolov5 预测输出的是带标记框的图⽚,所以需要先将预测的数据输出为⽂本格式,如json。  可以参考我之前的博客 json⽂件格式如下图

[ {

\"name\":\"01_05_0002.jpg\ \"category\":\"1\ \"bbox\":[ 3550, 1813, 4106, 2468 ],

\"score\":0.9482421875 }, {

\"name\":\"01_05_0002.jpg\ \"category\":\"1\ \"bbox\":[ 4041, 1655, 4570, 2291 ],

\"score\":0.9521484375 }]

2、测试图的标记数据

  因为使⽤的是 yolov5 ,所以测试集的标记数据和训练集⼀样都是 txt 格式的标注数据

3、将预测数据和标注数据匹配

  ⼀个测试图中可能存在好⼏个⽬标物,那预测数据和标注数据中就会存在好⼏个标注框,计算两个框的交集⾯积,交集⾯积最⼤的两个框才是互相匹配

的。

计算两个矩形框的交集⾯积

def label_area_detect(label_bbox_list, detect_bbox_list):

x_label_min, y_label_min, x_label_max, y_label_max = label_bbox_list

x_detect_min, y_detect_min, x_detect_max, y_detect_max = detect_bbox_list

if (x_label_max <= x_detect_min or x_detect_max < x_label_min) or ( y_label_max <= y_detect_min or y_detect_max <= y_label_min): return 0 else:

lens = min(x_label_max, x_detect_max) - max(x_label_min, x_detect_min) wide = min(y_label_max, y_detect_max) - max(y_label_min, y_detect_min) return lens * wide

4、多分类 precision 和 recall 的计算

  将预测数据和标注数据匹配算出⼀个 N*N 的矩阵

4、代码

import osimport json

import numpy as npfrom PIL import Image

# class name

classes = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']# 初始化⼆维0数组

result_list = np.array(np.zeros([len(classes), len(classes)]))# 获取图⽚宽⾼

def get_image_width_high(full_image_name): image = Image.open(full_image_name)

image_width, image_high = image.size[0], image.size[1] return image_width, image_high

# 读取原始标注数据

def read_label_txt(full_label_name, full_image_name): fp = open(full_label_name, mode=\"r\") lines = fp.readlines()

image_width, image_high = get_image_width_high(full_image_name) object_list = [] for line in lines:

array = line.split()

x_label_min = (float(array[1]) - float(array[3]) / 2) * image_width x_label_max = (float(array[1]) + float(array[3]) / 2) * image_width y_label_min = (float(array[2]) - float(array[4]) / 2) * image_high y_label_max = (float(array[2]) + float(array[4]) / 2) * image_high

bbox = [round(x_label_min, 2), round(y_label_min, 2), round(x_label_max, 2), round(y_label_max, 2)] category = int(array[0]) obj_info = {

'category' : category, 'bbox' : bbox }

object_list.append(obj_info) return object_list

# 计算交集⾯积

def label_area_detect(label_bbox_list, detect_bbox_list):

x_label_min, y_label_min, x_label_max, y_label_max = label_bbox_list

x_detect_min, y_detect_min, x_detect_max, y_detect_max = detect_bbox_list

if (x_label_max <= x_detect_min or x_detect_max < x_label_min) or ( y_label_max <= y_detect_min or y_detect_max <= y_label_min): return 0 else:

lens = min(x_label_max, x_detect_max) - max(x_label_min, x_detect_min) wide = min(y_label_max, y_detect_max) - max(y_label_min, y_detect_min) return lens * wide

# label 匹配 detect

def label_match_detect(image_name, label_list, detect_list): for label in label_list: area_max = 0 area_category = 0

label_category = label['category'] label_bbox = label['bbox'] for detect in detect_list:

if detect['name'] == image_name: detect_bbox = detect['bbox']

area = label_area_detect(label_bbox, detect_bbox) if area > area_max: area_max = area

area_category = detect['category']

result_list[int(label_category)][classes.index(str(area_category))] += 1

def main():

image_path = '../image_data/seed/test/images/' # 图⽚⽂件路径 label_path = '../image_data/seed/test/labels/' # 标注⽂件路径 detect_path = 'result.json' # 预测的数据 precision = 0 # 精确率 recall = 0 # 召回率 # 读取 预测 ⽂件数据

with open(detect_path, 'r') as load_f: detect_list = json.load(load_f) # 读取图⽚⽂件数据

all_image = os.listdir(image_path) for i in range(len(all_image)):

full_image_path = os.path.join(image_path, all_image[i]) # 分离⽂件名和⽂件后缀

image_name, image_extension = os.path.splitext(all_image[i]) # 拼接标注路径

full_label_path = os.path.join(label_path, image_name + '.txt') # 读取标注数据

label_list = read_label_txt(full_label_path, full_image_path) # 标注数据匹配detect

label_match_detect(all_image[i], label_list, detect_list) # print(result_list)

for i in range(len(classes)):

row_sum, col_sum = sum(result_list[i]), sum(result_list[r][i] for r in range(len(classes))) precision += result_list[i][i] / float(col_sum) recall += result_list[i][i] / float(row_sum)

print(f'precision: {precision / len(classes) * 100}% recall: {recall / len(classes) * 100}%')

if __name__ == '__main__': main()

  输出:

因篇幅问题不能全部显示,请点此查看更多更全内容