物体检测性能评价指标:IoU、mAP、P-R曲线

IoU是Intersection of Union的缩写,中文意思为:并集交点
IoU表示真实框和预测框的重合程度,取值区间为[0,1],IoU值越大,表明两个框重合越好
IoU的计算公式:
在这里插入图片描述
在这里插入图片描述

IoU代码(python):

def iou(boxA,boxB):
    #计算重合部分的上、下、左、右4个边的值,注意最大最小函数的使用
    left_max = max(boxA[0],boxB[0])  #boxA[0]:真实框的左边值 boxB[0]:预测框的左边值
    top_max = max(boxA[1],boxB[1])   #boxA[1]:真实框的上边值 boxB[0]:预测框的上边值
    right_min = min(boxA[2],boxB[2])  #boxA[2]:真实框的右边值 boxB[2]:预测框的右边值
    bottom_min = min(boxA[3],boxB[3])  #boxA[3]:真实框的下边值 boxB[3]:预测框的下边值
    #计算重合部分的面积
    inter = max(0,(right_min - left_max) )* max(0,(bottom_min-top_max))
    Sa = (boxA[2] - boxA[0])*(boxA[3] - boxA[1])
    Sb = (boxB[2] - boxB[0])*(boxB[3] - boxB[1])
    #计算所有区域的面积并计算iou
    union = Sa + Sb - inter
    iou = inter/union
    return iou

对于IoU而言,我们通常选取一个阈值,如0.5,来确定检测框是正确的还是错误的。当两个框的IoU大于0.5时,我们认为时一个有效的检测,否则输入无效的检测。

由于图像中存在背景与物体两种标签,预测框也分为正确和错误,因此在评测时会产生以下四种样本:

  • 正确检测框TP(True Positive):预测框正确地与标签框匹配,IoU大于0.5
  • 误检框FP(False Positive):将背景预测成了物体,通常这种框与图中是所有标签的IoU都不会超过0.5
  • 漏检框FN(False Negative):本来需要模型检测出的物体,模型没有检测出
  • 正确背景(True Negative):本身是背景,模型也没有检测出来,通常在物体检测中不考虑

对于一个检测器,通常用mAP(mean Average Precision)这一指标来评价一个模型好坏(AP:个类别检测精度 mAP:多个类别的平均精度),评测需要每张图片的预测值与标签值,二者包含的内容如下:

  • 预测值(Dets):物体类别、边框位置的四个预测值、该物体的得分
  • 标签值(GTs):物体类别、边框位置的四个真实值

AP计算过程图:
我们首先将所有的预测框按照得分从高到低进行排序,然后从高到低遍历预测框
在这里插入图片描述
在遍历完所有预测框后,我们会得到每一个预测框是否正确,即TP或FP,在遍历过程中我们可以通过TP和FP的数量来计算模型的召回率和准确率
召回率(Recall,R):当前一共检测出的标签框与所有标签框的比值
准确率(Precision,P):当前遍历过的预测框中,属于正确预测边框的比值
计算公式:
在这里插入图片描述
遍历到每一个预测框时,都可以生成对应的P和R,这两个值可以组成一个点(R,P),将这些点绘制成曲线,就形成了P-R曲线,如下图
在这里插入图片描述
不过,即使有了P-R曲线,评价模型依旧不是非常直观,因为不能在曲线上直接选取到合适的点,召回率高的时候准确率会很低,准确率高的时候召回率往往很低,这个时候AP就派上用场了,计算公式如下:
在这里插入图片描述
从公式可以看出AP代表了曲线的面积,总和考虑了不同召回率下的准确率,不会对P和R有任何偏好
除了求面积的方式,还可以使用不同召回率对应的准确率求平均的方式求AP
每个类别的AP是相互独立的,将每个类别的AP进行平均,就得到了mAP
(严格意义上来讲,需要对曲线进行一定的修正再进行AP的计算)

AP过程代码(python):

det_boxes:包含全部图像中所有类别的预测框,其中一个表框包含了[left,top,right,bottom,score,NameofImage]
gt_boxes:包含了全部图像中所有类别的标签,其中一个标签的内容为[left,top,right,bottom,0],最后一位0代表该标签没有被匹配过,如果匹配过则会置为1,其它预测框再去匹配则为误检框

  • left:左边值
  • top:上边值
  • right:右边值
  • bottom:下边值
  • score:得分
  • Nameoflmage:图像名称(标签)
for c in classes:
    #通过类别作为关键字,得到每个类别的预测、标签及总标签数
    dects = det_boxes[c]
    gt_class = gt_boxes[c]
    npos = num_pos[c]
    #利用得分作为关键字,对预测框按照得分从高到低排序
    dect = sorted(dects,key = lambda conf: conf[4],reverse = True)
    #设置两个与预测边框长度相同的列表,标记是True Positive还是False Positive
    TP = np.zeros(len(dects))
    FP = np.zeros(len(dects))
    #对某一个类别的预测框进行遍历
    for d in range(len(dects)):
        #将IoU默认置为最低
        iouMax = sys.float_info.min
        #遍历与预测框同一图像中的同一类别的标签,计算IoU
        if dects[d][-1] in gt_class:
            for j in range(len(gt_class[dects[d][-1]])):
                iou = Evaluator.iou(dects[d][:4],gt_class[dects[d][-1]][j][:4])
                    if iou > iouMax:
                        iouMax = iou
                        jmax = j    #记录与预测有最大IoU的标签
            #如果最大IoU大于阈值,并没有被匹配通过则赋予TF
            if iouMax >= cfg['iouThreshold']:
                if gt_class[dects[d][-1]][jmax][4] == 0:
                    TP[d] = 1
                    gt_class[dects[d][-1]][jmax][4] = 1
                #如果被匹配过,赋予FP
                else:
                    FP[d] = 1
            #如果最大IoU没有超过阈值,赋予FP
            else:
                FP[d] = 1
        #如果对应图像中没有该类别的标签,赋予FP
        else:
            FP[d] = 1
    #利用Numpy的cumsum()函数,计算累计的FP与TP
    acc_FP = np.cumsum(FP)
    acc_TP = np.cumsum(TP)
    rec = acc_TP/npos    #得到每个点的Recall
    prec = np.divide(acc_TP,(acc_FP + acc_TP))    #得到每个点的Precision
    #利用Recall与Precision进一步计算得到AP
    [ap,mpre,mrec,ii] = Evaluator.CalculateAveragePrecision(rec,prec)
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁天牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值