Bootstrap

目标检测—查全率和查准率Python代码实现

目标检测查全率和查准率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’, ‘’)

;