第二十六章 解读IoU、GIoU、DIoU、CIoU、EIoU 5大评价指标

news2024/11/25 18:32:48

目录

一、简介

二、IoU(Intersection over Union)

三、GIoU(Generalized IoU)

四、DIoU(Distance-IoU)

五、CIoU(Complete-IoU)

六、EIoU(Efficient-IoU)

七、pytorch代码实现

八、总结


一、简介

​ 在目标检测任务中,常用到一个指标IoU,即交并比,IoU可以很好的描述一个目标检测模型的好坏。在训练阶段IoU可以作为anchor-based方法中,划分正负样本的依据;同时也可用作损失函数;在推理阶段,NMS中会用到IoU。同时IoU有着比较严重的缺陷,于是出现了GIoU、DIoU、CIoU、EIoU,下面我们一起看一下这几种IoU。

二、IoU(Intersection over Union)

​ IoU的计算是用预测框(A)和真实框(B)的交集除以二者的并集,其公式为:

img

​ IoU的值越高也说明A框与B框重合程度越高,代表模型预测越准确。反之,IoU越低模型性能越差。

IoU优点:

​ (1)IoU具有尺度不变性

​ (2)结果非负,且范围是(0, 1)

IoU缺点:

​ (1)如果两个目标没有重叠,IoU将会为0,并且不会反应两个目标之间的距离,在这种无重叠目标的情况下,如果IoU用作于损失函数,梯度为0,无法优化。

​ (2)IoU无法精确的反映两者的重合度大小。如下图所示,三种情况IoU都相等,但看得出来他们的重合度是不一样的,左边的图回归的效果最好,右边的最差。

20190413221630196.png?x-oss-process=image

三、GIoU(Generalized IoU)

​ 论文地址:https://arxiv.org/pdf/1902.09630.pdf

​ 为了解决IoU作为损失函数时的两个缺点,有大神提出了GIoU,在IoU后面增加了一项,计算两个框的最小外接矩形,用于表征两个框的距离,从而解决了两个目标没有交集时梯度为零的问题,公式为:

img

​ 其中C是两个框的最小外接矩形的面积。

​ 当IOU=0时:

img

​ 当IOU为0时,意味着A与B没有交集,这个时候两个框离得越远,GIOU越接近-1;两框重合,GIOU=1,所以GIOU的取值为(-1, 1]。

e69353e206f6448db8fb6f381b0a3c3c.png

​ GIOU作为loss函数时:

img

​ 当A、B两框不相交时gif.latex?A%5Ccup%20B不变,最大化GIoU就是最小化C,这样就会促使两个框不断靠近。

优点:

​ (1)当IoU=0时,仍然可以很好的表示两个框的距离。

​ (2)GIoU不仅关注重叠区域,还关注其他的非重合区域,能更好的反映两者的重合度。

缺点:

​ (1)当两个框属于包含关系时,GIoU会退化成IoU,无法区分其相对位置关系,如下图:

4af195ddac92494ab64f3b1d4231870d.png

​ (2)由于GIoU仍然严重依赖IoU,因此在两个垂直方向,误差很大,很难收敛。两个框在相同距离的情况下,水平垂直方向时,此部分面积最小,对loss的贡献也就越小,从而导致在垂直水平方向上回归效果较差。

​ 如下图,三种情况下GIoU的值一样,GIoU将很难区分这种情况。

c7998ce5d28f412487ebddb8f18c312d.png

四、DIoU(Distance-IoU)

​ 论文地址:https://arxiv.org/pdf/1911.08287.pdf

​ 针对上述GIoU的两个问题,有大神将GIoU中最小外接框来最大化重叠面积的惩罚项修改成最小化两个BBox中心点的标准化距离从而加速损失的收敛过程,这就诞生了DIoU。

​ DIoU要比GIou更加符合目标框回归的机制,将目标与预测之间的距离,重叠率以及尺度都考虑进去,使得目标框回归变得更加稳定,不会像IoU和GIoU一样出现训练过程中发散等问题。

​ 公式如下:

img

​ 其中gif.latex?b%2Cb%5E%7Bgt%7D分别代表了预测框和真实框的中心点,且 ρ 代表的是计算两个中心点间的欧式距离。 c 代表的是能够同时包含预测框和真实框的最小外接矩形的对角线长度。

ee2a4bd2bed34d08ad3ab5014fe4048b.png

优点:

​ (1)DIoU loss可以直接最小化两个目标框的距离,因此比GIoU loss收敛快得多。

​ (2)对于包含两个框在水平方向和垂直方向上这种情况,DIoU损失可以使回归非常快。

​ (3)DIoU还可以替换普通的IoU评价策略,应用于NMS中,使得NMS得到的结果更加合理和有效。

缺点:

​ 虽然DIOU能够直接最小化预测框和真实框的中心点距离加速收敛,但是Bounding box的回归还有一个重要的因素纵横比暂未考虑。如下图,三个红框的面积相同,但是长宽比不一样,红框与绿框中心点重合,这时三种情况的DIoU相同,证明DIoU不能很好的区分这种情况。

59747cf882fb43db94ce9f45fa83c0ff.png

五、CIoU(Complete-IoU)

​ CIoU与DIoU出自同一篇论文,CIoU大多数用于训练。DIoU的作者考虑到,在两个框中心点重合时,c与d的值都不变。所以此时需要引入框的宽高比:

img

​ 其中α是权重函数,v用来度量宽高比的一致性:

img

img

​ 最终CIoU Loss定义为:

img

优点:

​ 考虑了框的纵横比,可以解决DIoU的问题。

缺点:

​ 通过CIoU公式中的v反映的纵横比的差异,而不是宽高分别与其置信度的真实差异,所以有时会阻碍模型有效的优化相似性。

六、EIoU(Efficient-IoU)

​ 论文地址:https://arxiv.org/pdf/2101.08158.pdf

​ 为了解决CIoU的问题,有学者在CIOU的基础上将纵横比拆开,提出了EIOU Loss,并且加入Focal聚焦优质的预测框,与CIoU相似的,EIoU是损失函数的解决方案,只用于训练。

​ EIOU的惩罚项是在CIOU的惩罚项基础上将纵横比的影响因子拆开分别计算目标框和预测框的长和宽,该损失函数包含三个部分:重叠损失,中心距离损失,宽高损失,前两部分延续CIoU中的方法,但是宽高损失直接使目标框与预测框的宽度和高度之差最小,使得收敛速度更快。惩罚项公式如下:

img

​ 其中imgimg是覆盖两个Box的最小外接框的宽度和高度。

​ 通过整合EIoU Loss和FocalL1 loss,最终得到了最终的Focal-EIoU loss,其中 γ是一个用于控制曲线弧度的超参。

img

优点:

1)将纵横比的损失项拆分成预测的宽高分别与最小外接框宽高的差值,加速了收敛提高了回归精度。

2)引入了Focal Loss优化了边界框回归任务中的样本不平衡问题,即减少与目标框重叠较少的大量锚框对BBox 回归的优化贡献,使回归过程专注于高质量锚框。

七、pytorch代码实现

​ 代码中使用pytorch是方便在作为损失函数的时候,方便反向传播,下面的代码计算各种IoU,用作损失函数的时候需要用1减去返回结果。

import torch
import math
import numpy as np
 
 
def bbox_iou(box1, box2, xywh=False, giou=False, diou=False, ciou=False, eiou=False, eps=1e-7):
    """
    实现各种IoU
    Parameters
    ----------
    box1        shape(b, c, h, w,4)
    box2        shape(b, c, h, w,4)
    xywh        是否使用中心点和wh,如果是False,输入就是左上右下四个坐标
    GIoU        是否GIoU
    DIoU        是否DIoU
    CIoU        是否CIoU
    EIoU        是否EIoU
    eps         防止除零的小量
    Returns
    -------
    """
    # 获取边界框的坐标
    # 判断输入的box数据格式,如果为xywh,则将其转换为xyxy格式
    if xywh:
        # xywh转为xyxy,对于box1和box2分别进行操作
        # box1和box2是包含四个元素的张量,这四个元素分别是x, y, w, h
        # 这里的xy1和xy2是将原始的box1和box2的坐标中心点计算出来,然后根据新的宽度和高度(原宽度和高度的算术平均值)计算出新的坐标范围
        b1_x1, b1_x2 = box1[..., 0] - box1[..., 2] / 2, box1[..., 0] + box1[..., 2] / 2
        b1_y1, b1_y2 = box1[..., 1] - box1[..., 3] / 2, box1[..., 1] + box1[..., 3] / 2
        b2_x1, b2_x2 = box2[..., 0] - box2[..., 2] / 2, box2[..., 0] + box2[..., 2] / 2
        b2_y1, b2_y2 = box2[..., 1] - box2[..., 3] / 2, box2[..., 1] + box2[..., 3] / 2
    else:
        # 如果输入的box数据格式不是xywh,则直接使用输入的box数据(x1, y1, x2, y2)
        # box1和box2是包含四个元素的张量,这四个元素分别是x1, y1, x2, y2
        b1_x1, b1_y1, b1_x2, b1_y2 = box1[..., 0], box1[..., 1], box1[..., 2], box1[..., 3]
        b2_x1, b2_y1, b2_x2, b2_y2 = box2[..., 0], box2[..., 1], box2[..., 2], box2[..., 3]

    # 计算两个box的交集面积
    # inter = (torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0) * \
    #         (torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)).clamp(0)
    inter = torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)  # 行交集
    inter = torch.min(inter, torch.zeros_like(inter))  # 对可能出现的负值使用零进行替换
    inter = inter.clamp(0)  # 对可能出现的负值使用零进行替换
    inter = inter * torch.min(b1_y2, b2_y2) - torch.max(b1_y1, b2_y1)  # 列交集
    inter = torch.min(inter, torch.zeros_like(inter))  # 对可能出现的负值使用零进行替换
    inter = inter.clamp(0)  # 对可能出现的负值使用零进行替换

    # 计算两个box的并集面积(不考虑重叠部分)
    w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1 + eps  # box1的宽和高
    w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1 + eps  # box2的宽和高
    union = w1 * h1 + w2 * h2 - inter + eps  # 并集面积,需要减去交集部分以避免重复计算

    # 计算IOU(Intersection over Union)值,即两个box的交集面积除以两个box的并集面积
    iou = inter / union  # IOU值
 
    # 判断是否需要计算GIoU、DIoU、CIoU、EIoU中的至少一种
    if giou or diou or ciou or eiou:
        # 计算两个box的最小外接矩形的宽度和高度
        # 矩形的左上和右下坐标分别为(b1_x1, b1_y1)和(b1_x2, b1_y2),(b2_x1, b2_y1)和(b2_x2, b2_y2)
        cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1)
        ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, b2_y1)

        # 如果需要计算CIoU、DIoU、EIoU中的至少一种
        if ciou or diou or eiou:
            # 计算最小外接矩形角线的平方
            c2 = cw ** 2 + ch ** 2 + eps  # eps是防止除数为0的微小值
            # 计算最小外接矩形中点距离的平方
            rho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 +
                    (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4
            # 如果需要计算DIoU
            if diou:
                # 输出DIoU
                return iou - rho2 / c2
            # 如果需要计算CIoU
            elif ciou:
                v = (4 / math.pi ** 2) * torch.pow(torch.atan(w2 / h2) - torch.atan(w1 / h1), 2)
                with torch.no_grad():
                    alpha = v / (v - iou + (1 + eps))  # eps是防止除数为0的微小值
                # 输出CIoU
                return iou - (rho2 / c2 + v * alpha)
            # 如果需要计算EIoU
            elif eiou:
                rho_w2 = ((b2_x2 - b2_x1) - (b1_x2 - b1_x1)) ** 2
                rho_h2 = ((b2_y2 - b2_y1) - (b1_y2 - b1_y1)) ** 2
                cw2 = cw ** 2 + eps  # eps是防止除数为0的微小值
                ch2 = ch ** 2 + eps  # eps是防止除数为0的微小值
                # 输出EIoU
                return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2)
        else:
            # 计算凸包面积(最小外接矩形的面积)
            c_area = cw * ch + eps  # eps是防止除数为0的微小值
            # 输出GIoU,GIoU是GIoU、CIoU、DIoU、EIoU之外的IoU变种,它的计算方式和IoU相同,只是最后用凸包面积代替了交集面积
            return iou - (c_area - union) / c_area
    else:
        # 如果不需要计算任何IoU的变种,则直接输出原始的IoU值
        # 这里的iou应该是在函数外部定义的变量,表示两个box的交集面积除以两个box的并集面积
        return iou

 
if __name__ == '__main__':
    box1 = torch.from_numpy(np.asarray([170, 110, 310, 370]))
    box1 = box1.expand(1, 1, 1, 1, 4)
    # 有交集
    box2 = torch.from_numpy(np.asarray([250, 60, 375, 300]))
    box2 = box2.expand(1, 1, 1, 1, 4)
    # 无交集
    box3 = torch.from_numpy(np.asarray([730, 420, 1000, 700]))
    box3 = box3.expand(1, 1, 1, 1, 4)
    print('iou有交集:', bbox_iou(box1, box2))
    print('giou有交集:', bbox_iou(box1, box2, giou=True))
    print('diou有交集:', bbox_iou(box1, box2, diou=True))
    print('ciou有交集:', bbox_iou(box1, box2, ciou=True))
    print('eiou有交集:', bbox_iou(box1, box2, eiou=True))
    print("=" * 20)
    print('iou无交集:', bbox_iou(box1, box3))
    print('giou无交集:', bbox_iou(box1, box3, giou=True))
    print('diou无交集:', bbox_iou(box1, box3, diou=True))
    print('ciou无交集:', bbox_iou(box1, box3, ciou=True))
    print('eiou无交集:', bbox_iou(box1, box3, eiou=True))
 

八、总结

​ 边界框回归的三大几何因素:重叠面积、中心点距离、纵横比。

重叠中心点纵横比优点缺点
IoU××尺度不变性,非负性;同一性;对称性;三角不等性。1.如果两个框不相交,不能反映两个框距离远近 2.无法精确的反映两个框的重合度大小
GIoU××解决检测框和真实框没有重叠时loss等于0问题1.当检测框和真实框出现包含现象的时候GIOU退化成IOU2.两个框相交时,在水平和垂直方向上收敛慢
DIoU×直接回归两个框中心点的欧式距离,加速收敛。回归过程中未考虑Bounding box的纵横比,精确度上尚有进一步提升的空间
CIoU增加了检测框尺度的loss,增加了长和宽的loss,这样预测框就会更加的符合真实框。1. 纵横比描述的是相对值,存在一定的模糊2. 未考虑难易样本的平衡问题
EIoU分别计算宽高的差异值取代了纵横比,同时引入Focal Loss解决难易样本不平衡的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1260283.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用DeepBlueCLI对Windows日志进行取证(小记)

什么是Windows日志取证 Windows日志取证是指通过分析和收集Windows操作系统生成的日志信息,以获取关于系统活动、用户行为、安全事件等方面的数据 工具使用 工具介绍 DeepBlueCLI 是一个用于检测 Windows 系统中的安全事件和威胁的 PowerShell 脚本工具 工具下…

探究Kafka原理-4.API使用

👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring源码、JUC源码、Kafka原理🔥如果感觉博主的文章还不错的话,请&#x1f44…

Kotlin学习之集合

原文链接 Kotlin Collections 现代的软件一般比较复杂,程序语言中的基本数据类型往往不能满足需要,除了基本的数据类型以外,还有对象的容器也非常的重要,比如线性容器(数组,列表和Set)和二维容…

Adversarial Attack and Defense on Graph Data: A Survey(2022 IEEE Trans)

Adversarial Attack and Defense on Graph Data: A Survey----《图数据的对抗性攻击和防御:综述》 图对抗攻击论文数据库: https://github.com/safe-graph/graph-adversarial-learning-literature 摘要 深度神经网络(DNN)已广泛应…

360压缩安装一半不动了?一分钟解决!

360压缩软件是我们常用的压缩软件,但是常常会遇到压缩安装到一半停止的情况,下面提供了一些可能的原因和解决办法,大家可以进行尝试~ 方法一:关闭防火墙和杀毒软件 有时候,防火墙和杀毒软件可能会阻止360压缩的安装过…

计算机组成原理——存储器(主存容量扩展)

对于字扩展与位扩展的解释: 计算机原理中的字,位扩展,都给老子进来学,看不懂算我输! 如果主存的容量无法满足 CPU 的需求,可以通过存储器扩展来解决,扩展的方式有两种: 主存的位数…

java学习part17

110-面向对象(高级)-关键字final的使用及真题_哔哩哔哩_bilibili 1.概念 tips:java里有const关键字,但是用于保留字,不会使用,目前没有意义。 final变量没有默认赋值,只能在以下三个地方赋值,且只能赋值一…

『VUE3后台—大事件管理系统』

项目地址:https://gitee.com/csheng-gitee/vue3-big-event-admin 技术栈:VUE3 + Pinia + Pnpm(本项目暂不用 typescript) 一、前期准备工作 1、创建项目 npm install -g pnpm pnpm create vue2、ESLint 配置 (1) 禁用 prettier 插件,下载 ESLint 插件;(2) 在 vscode 的…

好题分享(2023.11.19——2023.11.25)

目录 ​编辑 前情回顾: 前言: 认识循环队列: 实现循环队列的思路: 题目:《设计循环队列》 1.判满和判空: 2.添加数据和删除 3.计算循环队列的数据个数 4.返回对队尾元素 总结: 前情回…

内部类, Comparable接口, Comparator接口, Cloneable接口 ---java

目录 一. 内部类 1.1 静态内部类 1.2 实例内部类 1.3匿名内部类 二. 接口的使用实例 2.1 Comparable接口 2.2 Comparator接口 ---比较器 2.3 Cloneable接口 深拷贝浅拷贝 一. 内部类 当一个事物的内部,还有一个部分需要一个完整的结构进行描述&#xff0…

从零开始学Go web——第一天

文章目录 从零开始学Go web——第一天一、Go与web应用简介1.1 Go的可扩展性1.2 Go的模块化1.3 Go的可维护1.4 Go的高性能 二、web应用2.1 工作原理2.2 各个组成部分2.2.1 处理器2.2.2 模板引擎 三、HTTP简介四、HTTP请求4.1 请求的文本数据4.2 请求方法4.2.1 请求方法类型4.2.2…

C语言:输出所有“水仙花数”。“水仙花数”是指一个3位数,其各位数字的立方和等于该数本身,如153=1^3 +5^3+3^3

分析: 在主函数 main 中,程序首先定义四个整型变量 m、a、b 和 c,并用于计算和判断水仙花数。然后使用 printf 函数输出提示信息。 接下来,程序使用 for 循环结构,从 100 到 999 遍历所有三位数。对于每个遍历到的数 m…

C#常见的设计模式-创建型模式

引言 在软件开发过程中,设计模式是一种被广泛采用的思想和实践,可以提供一种标准化的解决方案,以解决特定问题。设计模式分为三种类型:创建型模式、结构型模式和行为型模式。本篇文章将重点介绍C#中常见的创建型模式。 目录 引言…

python实现自动刷平台学时

背景 前一阵子有个朋友让我帮给小忙,因为他每学期都要看视频刷学时,一门平均需要刷500分钟,一学期有3-4门需要刷的。 如果是手动刷的话,比较麻烦,能否帮他做成自动化的。搞成功的话请我吃饭。为了这顿饭,咱…

Elasticsearch:什么是非结构化数据?

非结构化数据定义 非结构化数据是指未按照设计的模型或结构组织的数据。 非结构化数据通常被归类为定性数据,可以是人类或机器生成的。 非结构化数据是最丰富的可用数据类型,经过分析后,可用于指导业务决策并在许多其他用例中实现业务目标。…

正则表达式和awk

目录 一、正则表达式 1.正则表达式基本介绍 2.正则表达式分类 3.基本正则表达式分类 4.代表字符 5.表示次数 6.位置锚定 7.分组或其他 8.扩展正则表达式 二、awk 1.语法 2.选项 3.基础用法 4.内置变量 5.条件判断 6.数组 总结:本章主要介绍了正则表…

【C++】map与set

​👻内容专栏:C/C编程 🐨本文概括:关联式容器的介绍、set、multiset、map、multimap。 🐼本文作者:阿四啊 🐸发布时间:2023.11.27 一、关联式容器的介绍 在之前C的学习之中&#xf…

STM32入门--看门狗

一、独立看门狗简介 STM32F10xxx内置两个看门狗,提供了更高的安全性、时间的精确性和使用的灵活性。两个看门狗设备(独立看门狗和窗口看门狗)可用来检测和解决由软件错误引起的故障;当计数器达到给定的超时值时,触发一个中断(仅适用于窗口型看…

【vue】a-table的斑马纹以及hover样式的修改:

文章目录 一、效果:二、实现(以jeecg为例): 一、效果: 二、实现(以jeecg为例): // 设置基数行样式 // .ant-table-tbody tr:nth-child(n) { // color: #fff; // }// hover时候每行…

如何使用 Java 在Excel中创建下拉列表

下拉列表(下拉框)可以确保用户仅从预先给定的选项中进行选择,这样不仅能减少数据输入错误,还能节省时间提高效率。在MS Excel中,我们可以通过 “数据验证” 提供的选项来创建下拉列表,但如果要在Java程序中…