物体分类和目标检测性能评价指标

                                                        物体分类和目标检测性能评价指标

 

 

 

参考链接:

  1. https://blog.csdn.net/katherine_hsr/article/details/79266880
  2. https://github.com/AlexeyAB/darknet#how-to-compile-on-windows
  3. https://www.jianshu.com/p/665f9f168eff

不要走开.....看下面

python代码:

##-*- coding:utf-8-*-

#通用目标检测模型评价脚本 For unique class
#评价指标:1) AP for the unigue class
#              2) AVE_IOU
#              3) F1-Score
#              4) TP  FP FN
#              5) Precision
#              6) Recall

#Author: SyGoing
#Date: 2018.08.16-2018.08.17(Have finished,Just wait for TEST)
#Refer: The Method of VOC DataSet

#input:
        # 1 Test images
        # 2 Gound Truth labels
        # 3 detection result

#output: AP    Recall   Precision    TP(正确)   FP(误检) FN(漏检)  AVE_IOU   F1-score


import numpy as np
import xml.etree.ElementTree as ET
import cv2
import os

#类型ID
classes = ["person", "car"]

def searchFile(filename,fieltype,filelist):
    search_id=-1
    for file in filelist:
        name= os.path.splitext(file)[0]  # 文件名
        type= os.path.splitext(file)[1]  # 文件扩展名
        search_id+=1
        if filename==name and fieltype==type:
           break
    return filelist[search_id]

def getLabelNum(objs_t,classname):
    count=0
    for obj in objs_t:
        if obj['name']==classname:
            count+=1
    return count

def voc_ap(rec, prec, use_07_metric=False):
    """ ap = voc_ap(rec, prec, [use_07_metric])
    Compute VOC AP given precision and recall.
    If use_07_metric is true, uses the
    VOC 07 11 point method (default:False).
    """
    if use_07_metric:
        # 11 point metric
        ap = 0.
        for t in np.arange(0., 1.1, 0.1):
            if np.sum(rec >= t) == 0:
                p = 0
            else:
                p = np.max(prec[rec >= t])
            ap = ap + p / 11.
    else:
        # correct AP calculation
        # first append sentinel values at the end
        mrec = np.concatenate(([0.], rec, [1.]))
        mpre = np.concatenate(([0.], prec, [0.]))

        # compute the precision envelope
        for i in range(mpre.size - 1, 0, -1):
            mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])

        # to calculate area under PR curve, look for points
        # where X axis (recall) changes value
        i = np.where(mrec[1:] != mrec[:-1])[0]

        # and sum (\Delta recall) * prec
        ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
    return ap

#ground truth in VOC xml for per image
def loadGroundTruth_XML(xmlfile):
    objects = []
    """ groundType=0:Parse a PASCAL VOC xml file """
    tree = ET.parse(xmlfile)
    for obj in tree.findall('object'):
        obj_struct = {}
        obj_struct['name'] = obj.find('name').text
        bbox = obj.find('bndbox')
        obj_struct['bbox'] = [int(bbox.find('xmin').text),
                                int(bbox.find('ymin').text),
                                int(bbox.find('xmax').text),
                                int(bbox.find('ymax').text)]
        objects.append(obj_struct)
    return objects

#marked by yolo_mark for per image
def loadGroundTruth_TXT(txtfile,width,height):
    objects = []
    """ groundType=1:Parse a normal txt file :the file is yolo """

    with open(txtfile, 'r') as f:
        lines = f.readlines()

    splitlines = [x.strip().split(' ') for x in lines]
    for obj in splitlines:
        obj_struct = {}
        obj_struct['name']=classes[obj[0]]

        w = float(obj[3]) * float(width)
        h = float(obj[4])* float(height)
        xmin = float(obj[1]) * float(width) - w / 2
        ymin = float(obj[2]) * float(height) - h / 2
        xmax = w + xmin
        ymax = h + ymin

        obj_struct['bbox'] = [int(xmin), int(ymin), int(xmax), int(ymax)]
        objects.append(obj_struct)
    return objects

#per image detfile by txt
def loadDets(detfile):
    objects = []
    with open(detfile, 'r') as f:
        lines = f.readlines()

    splitlines = [x.strip().split(' ') for x in lines]
    for obj in splitlines:
        obj_struct = {}
        obj_struct['name'] = classes[obj[0]]
        obj_struct['conf']=obj[1]
        xmin=obj[2]
        ymin=obj[3]
        xmax=obj[4]+xmin
        ymax=obj[5]+ymin
        obj_struct['bbox'] = [int(xmin), int(ymin), int(xmax), int(ymax)]
        objects.append(obj_struct)
    return objects

def iou(box_t,box_d):
    inter_xmin = np.maximum(box_d[0], box_t[0])
    inter_ymin = np.maximum(box_d[1], box_t[1])
    inter_xmax = np.minimum(box_d[2], box_t[2])
    inter_ymax = np.minimum(box_d[3], box_t[3])

    inter_h = inter_ymax - inter_ymin
    inter_w = inter_xmax - inter_xmin

    uni = ((box_t[2] - box_t[0] + 1.) * (box_t[3] - box_t[1] + 1.) +
           (box_d[2] - box_d[0] + 1.) * (box_d[3] - box_d[1] + 1.) - inter_h * inter_w)

    return inter_h * inter_w / uni

def ObjectEval(detpath,truthpath,imagePath,className,truthtype,ovthresh=0.5,use_07_metric=True):

    npos=0
    fp=0
    tp=0
    det_num=0
    ave_iou=0

    #1 Truth Dets Images
    truth_annos=os.listdir(truthpath)
    detsfiles=os.listdir(detpath)
    imagefiles=os.listdir(imagePath)

    for truth in truth_annos:
        filenamet = os.path.splitext( truth)[0]  # 文件名
        filetypet = os.path.splitext( truth)[1]  # 文件扩展名
        if filetypet=='.xml':
            objects_t=loadGroundTruth_XML(os.path.join(truthpath,truth))
            detfile = searchFile(filenamet, '.txt', detsfiles)
            objects_d=loadDets(os.path.join(detpath,detfile))

            num = getLabelNum(objects_t, className)
            npos+=num

            for objd in objects_d:
                if objd['name']==className:
                    det_num+=1
                    if num==0:
                        fp+=1
                    else:
                        max_iou=-1
                        for objt in objects_t:
                            if objt['name']==className:
                                box_t=np.array(objt['bbox'].astype(float))
                                box_d=np.array(objd['bbox'].astype(float))
                                IOU= iou(box_d,box_t)
                                if IOU>max_iou:
                                    max_iou=IOU
                        if max_iou>ovthresh:
                            ave_iou+=max_iou
                            tp+=1
                        else:
                            fp+=1

    ave_iou=ave_iou/(tp+fp)
    prec=tp/(tp+fp)
    rec=tp/npos
    F1_score=2*prec*rec/(prec+rec)
    ap=voc_ap(rec, prec,  use_07_metric)

    return rec, prec,F1_score, ap,ave_iou

def ObjectEvalTEST1(detpath,truthpath,imagePath,className,truthtype,ovthresh=0.5,use_07_metric=True):
    npos = 0
    fp = 0
    tp = 0
    det_num = 0
    ave_iou = 0

    # 1 Truth Dets Images
    truth_annos = os.listdir(truthpath)
    detsfiles = os.listdir(detpath)
    imagefiles = os.listdir(imagePath)

    for truth in truth_annos:
        filenamet = os.path.splitext(truth)[0]  # 文件名
        filetypet = os.path.splitext(truth)[1]  # 文件扩展名

        # R = [obj for obj in recs[imagename] if obj['name'] == classname]
        objects_t = []
        objects_d = []
        if truthtype == 0 and filetypet == '.xml':
            objects_t = loadGroundTruth_XML(os.path.join(truthpath, truth))
        elif truthtype == 1 and filetypet == '.txt':
            imgFile = searchFile(filenamet, '.jpg', imagefiles)
            img = cv2.imread(os.path.join(imagePath, imgFile))
            objects_t = loadGroundTruth_TXT(os.path.join(truthpath, truth), img.shape[1], img.shape[0])

        num = getLabelNum(objects_t, className)
        npos += num

        detfile = searchFile(filenamet, '.txt', detsfiles)
        objects_d = loadDets(os.path.join(detpath, detfile))

        for objd in objects_d:
            if objd['name'] == className:
                det_num += 1
                if num == 0:
                    fp += 1
                else:
                    max_iou = -1
                    for objt in objects_t:
                        if objt['name'] == className:
                            box_t = np.array(objt['bbox'].astype(float))
                            box_d = np.array(objd['bbox'].astype(float))
                            IOU = iou(box_d, box_t)
                            if IOU > max_iou:
                                max_iou = IOU
                    if max_iou > ovthresh:
                        ave_iou += max_iou
                        tp += 1
                    else:
                        fp += 1

    ave_iou = ave_iou / (tp + fp)
    prec = tp / (tp + fp)
    rec = tp / npos
    F1_score = 2 * prec * rec / (prec + rec)
    ap = voc_ap(rec, prec, use_07_metric)

    return rec, prec, F1_score, ap, ave_iou

def ObjectEvalTEST2(detpath, truthpath, imagePath, className, truthtype, ovthresh=0.5, use_07_metric=True):
    npos = 0
    fp = 0
    tp = 0
    fn=0
    det_num = 0
    ave_iou = 0

    # 1 Truth and Dets and Images
    truth_annos = os.listdir(truthpath)
    detsfiles = os.listdir(detpath)
    imagefiles = os.listdir(imagePath)

    for truth in truth_annos:
        filenamet = os.path.splitext(truth)[0]  # 文件名
        filetypet = os.path.splitext(truth)[1]  # 文件扩展名

        objects_t = []
        if truthtype == 0 and filetypet == '.xml':
            objects_t = loadGroundTruth_XML(os.path.join(truthpath, truth))
        elif truthtype == 1 and filetypet == '.txt':
            imgFile = searchFile(filenamet, '.jpg', imagefiles)
            img = cv2.imread(os.path.join(imagePath, imgFile))
            objects_t = loadGroundTruth_TXT(os.path.join(truthpath, truth), img.shape[1], img.shape[0])

        detfile = searchFile(filenamet, '.txt', detsfiles)
        objects_d = loadDets(os.path.join(detpath, detfile))

        ValidTruth = [X for X in objects_t if X['name'] == className]
        ValidDets = [X for X in objects_d if X['name'] == className]

        numt=len(ValidTruth)
        numd=len(ValidDets)

        npos+=numt

        if numd==0 and numt!=0:
            fn+=numt
            continue
        elif numd!=0 and numt==0:
            fp+=numd
            continue
        elif numd==0 and numt==0:
            continue
        else:
            for objd in objects_d:
                if objd['name'] == className:
                    det_num += 1
                    max_iou = -1
                    for objt in objects_t:
                        if objt['name'] == className:
                            box_t = np.array(objt['bbox'].astype(float))
                            box_d = np.array(objd['bbox'].astype(float))
                            IOU = iou(box_d, box_t)
                            if IOU > max_iou:
                                max_iou = IOU
                    if max_iou > ovthresh:
                        ave_iou += max_iou
                        tp += 1
                    else:
                        fp += 1

    ave_iou = ave_iou / float(tp + fp)
    prec = float(tp) / float(tp + fp)
    rec = float(tp) / float(npos)
    F1_score = 2 * prec * rec / (prec + rec)
    ap = voc_ap(rec, prec, use_07_metric)

    return rec, prec,  ap, ave_iou,F1_score,tp,fp,fn

猜你喜欢

转载自blog.csdn.net/ouyangfushu/article/details/82622720