优化改进YOLOv5算法之添加GIoU、DIoU、CIoU、EIoU、Wise-IoU模块(超详细)

news2024/11/25 1:45:52

目录

1、IoU

1.1 什么是IOU

 1.2 IOU代码

2、GIOU

2.1 为什么提出GIOU

2.2 GIoU代码

3 DIoU 

3.1 为什么提出DIOU

3.2 DIOU代码

4 CIOU

4.1 为什么提出CIOU

4.2 CIOU代码

5 EIOU

5.1 为什么提出EIOU 

5.2 EIOU代码

6 Wise-IoU

7 YOLOv5中添加GIoU、DIoU、CIoU、EIoU、Wise-IoU损失函数


1、IoU

1.1 什么是IOU

论文链接为:UnitBox: An Advanced Object Detection Network

IoU 的全称为交并比(Intersection over Union),通过这个名称我们大概可以猜到 IoU 的计算方法。IoU 计算的是 “预测的边框” 和 “真实的边框” 的交集和并集的比值。计算过程如下:

其中,绿色面积代表预测框B与真实框A的交集A\cap B;则

IOU=\frac{A\cap B}{A\cup B}

显而易见,IOU的值越高也说明预测框与真实框重合程度越高,代表模型预测越准确,反之,IOU越低模型性能越差。 

但是,IOU作为损失函数会出现以下问题:

  • 如果两个框没有相交,根据定义,IoU=0,不能度量IoU为零距离远近的程度。同时因为loss=0,没有梯度回传,无法进行学习训练。
  • IoU无法精确的反映两者的重合度大小。如下图所示,三种情况IoU都相等,但看得出来他们的重合度是不一样的,左边的图回归的效果最好,右边的最差。

 1.2 IOU代码

import numpy as np
def Iou(box1, box2, wh=False):
    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)
    # 获取矩形框交集对应的左上角和右下角的坐标(intersection)
    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

2、GIOU

论文链接:Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regression

2.1 为什么提出GIOU

为了解决上面两个问题,这篇论文提出了GIOU。由于IoU是比值的概念,对目标物体的scale是不敏感的。然而目标检测任务中的BBox的回归损失(MSE loss, l1-smooth loss等)优化和IoU优化不是完全等价的,而且 Ln 范数对物体的scale也比较敏感,IoU无法直接优化没有重叠的部分。这篇论文提出可以直接把IoU设为回归的loss。

GIOU的计算很简单,对于两个bounding box A和B。我们可以算出其最小凸集(同时包含了预测框和真实框的最小框的面积)C,有了最小凸集,就可以计算GIOU,如下所示

从公式可以看出,GIOU有几个优点:

  • GIOU是IOU的下界,且取值范围为(-1, 1]。当两个框不重合时,IOU始终为0,不论A、B相隔多远,但是对于GIOU来说,A,B不重合度越高(离的越远),GIOU越趋近于-1。
  • GIOU其实就是在IOU的基础上减掉了一个东西,这个减掉的东西,避免了两个bbox不重合时Loss为0的情况;
  • 可导:这一点需要强调下,由于max,min,分段函数(比如ReLU)这些都是可导的,所以用1-GIOU作为Loss是可导的。
  • 与IoU只关注重叠区域不同,GIoU不仅关注重叠区域,还关注其他的非重合区域,能更好的反映两者的重合度。

但是GIOU同样存在一些问题,主要有:

  • 状态1、2、3都是预测框在目标框内部且预测框大小一致的情况,这时预测框和目标框的差集都是相同的,因此这三种状态的GIOU值也都是相同的,这时GIOU退化成了IOU,无法区分相对位置关系;
  • GIOU收敛较慢、回归不够准确。

2.2 GIoU代码

import numpy as np

def Giou_np(bbox_p, bbox_g):
    """
    :param bbox_p: predict of bbox(N,4)(x1,y1,x2,y2)
    :param bbox_g: groundtruth of bbox(N,4)(x1,y1,x2,y2)
    :return:
    """
    # for details should go to https://arxiv.org/pdf/1902.09630.pdf
    # ensure predict's bbox form
    x1p = np.minimum(bbox_p[:, 0], bbox_p[:, 2]).reshape(-1,1)
    x2p = np.maximum(bbox_p[:, 0], bbox_p[:, 2]).reshape(-1,1)
    y1p = np.minimum(bbox_p[:, 1], bbox_p[:, 3]).reshape(-1,1)
    y2p = np.maximum(bbox_p[:, 1], bbox_p[:, 3]).reshape(-1,1)

    bbox_p = np.concatenate([x1p, y1p, x2p, y2p], axis=1)
    # calc area of Bg
    area_p = (bbox_p[:, 2] - bbox_p[:, 0]) * (bbox_p[:, 3] - bbox_p[:, 1])
    # calc area of Bp
    area_g = (bbox_g[:, 2] - bbox_g[:, 0]) * (bbox_g[:, 3] - bbox_g[:, 1])

    # cal intersection
    x1I = np.maximum(bbox_p[:, 0], bbox_g[:, 0])
    y1I = np.maximum(bbox_p[:, 1], bbox_g[:, 1])
    x2I = np.minimum(bbox_p[:, 2], bbox_g[:, 2])
    y2I = np.minimum(bbox_p[:, 3], bbox_g[:, 3])
    I = np.maximum((y2I - y1I), 0) * np.maximum((x2I - x1I), 0)

    # find enclosing box
    x1C = np.minimum(bbox_p[:, 0], bbox_g[:, 0])
    y1C = np.minimum(bbox_p[:, 1], bbox_g[:, 1])
    x2C = np.maximum(bbox_p[:, 2], bbox_g[:, 2])
    y2C = np.maximum(bbox_p[:, 3], bbox_g[:, 3])

    # calc area of Bc
    area_c = (x2C - x1C) * (y2C - y1C)
    U = area_p + area_g - I
    iou = 1.0 * I / U

    # Giou
    giou = iou - (area_c - U) / area_c

    # loss_iou = 1 - iou loss_giou = 1 - giou
    loss_iou = 1.0 - iou
    loss_giou = 1.0 - giou
    return giou, loss_iou, loss_giou

# def giou_tf




if __name__ == '__main__':

    p = np.array([[21,45,103,172],
                  [34,283,155,406],
                  [202,174,271,255]])
    g = np.array([[59,106,154,230],
                  [71,272,191,419],
                  [257,244,329,351]])
    Giou_np(p, g)

3 DIoU 

论文连接:Distance-IoU Loss: Faster and Better Learning for Bounding Box Regression

3.1 为什么提出DIOU

一个好的目标框回归函数应该考虑三个重要几何因素:重叠面积、中心点距离,长宽比。

针对IOU和GIOU存在的问题,作者从两个方面进行考虑

  • 如何最小化预测框和目标框之间的归一化距离?
  • 如何在预测框和目标框重叠时,回归的更准确?

 针对第一个问题,提出了DIOU_Loss(Distance_IOU_Loss)

DIOU_Loss考虑了重叠面积中心点距离,当目标框包裹预测框的时候,直接度量2个框的距离,因此DIOU_Loss收敛的更快。DIOU损失的优点有:

  • 与GIoU loss类似,DIoU loss在与目标框不重叠时,仍然可以为边界框提供移动方向。
  • DIoU loss可以直接最小化两个目标框的距离,因此比GIoU loss收敛快得多。
  • 对于包含两个框在水平方向和垂直方向上这种情况,DIoU损失可以使回归非常快,而GIoU损失几乎退化为IoU损失。
  • DIoU还可以替换普通的IoU评价策略,应用于NMS中,使得NMS得到的结果更加合理和有效。

但DIOU同样存在缺点,那就是没有考虑到长宽比。比如下面三种情况,目标框包裹预测框,本来DIOU_Loss可以起作用。但预测框的中心点的位置都是一样的,因此按照DIOU_Loss的计算公式,三者的值都是相同的。

3.2 DIOU代码

def Diou(bboxes1, bboxes2):
    rows = bboxes1.shape[0]
    cols = bboxes2.shape[0]
    dious = torch.zeros((rows, cols))
    if rows * cols == 0:#
        return dious
    exchange = False
    if bboxes1.shape[0] > bboxes2.shape[0]:
        bboxes1, bboxes2 = bboxes2, bboxes1
        dious = torch.zeros((cols, rows))
        exchange = True
    # #xmin,ymin,xmax,ymax->[:,0],[:,1],[:,2],[:,3]
    w1 = bboxes1[:, 2] - bboxes1[:, 0]
    h1 = bboxes1[:, 3] - bboxes1[:, 1] 
    w2 = bboxes2[:, 2] - bboxes2[:, 0]
    h2 = bboxes2[:, 3] - bboxes2[:, 1]
    
    area1 = w1 * h1
    area2 = w2 * h2

    center_x1 = (bboxes1[:, 2] + bboxes1[:, 0]) / 2 
    center_y1 = (bboxes1[:, 3] + bboxes1[:, 1]) / 2 
    center_x2 = (bboxes2[:, 2] + bboxes2[:, 0]) / 2
    center_y2 = (bboxes2[:, 3] + bboxes2[:, 1]) / 2

    inter_max_xy = torch.min(bboxes1[:, 2:],bboxes2[:, 2:]) 
    inter_min_xy = torch.max(bboxes1[:, :2],bboxes2[:, :2]) 
    out_max_xy = torch.max(bboxes1[:, 2:],bboxes2[:, 2:]) 
    out_min_xy = torch.min(bboxes1[:, :2],bboxes2[:, :2])

    inter = torch.clamp((inter_max_xy - inter_min_xy), min=0)
    inter_area = inter[:, 0] * inter[:, 1]
    inter_diag = (center_x2 - center_x1)**2 + (center_y2 - center_y1)**2
    outer = torch.clamp((out_max_xy - out_min_xy), min=0)
    outer_diag = (outer[:, 0] ** 2) + (outer[:, 1] ** 2)
    union = area1+area2-inter_area
    dious = inter_area / union - (inter_diag) / outer_diag
    dious = torch.clamp(dious,min=-1.0,max = 1.0)
    if exchange:
        dious = dious.T
    return dious

4 CIOU

论文链接:Distance-IoU Loss: Faster and Better Learning for Bounding Box Regression

4.1 为什么提出CIOU

 CIOU论文考虑到bbox回归三要素中的长宽比还没被考虑到计算中,因此,进一步在DIoU的基础上提出了CIoU。其惩罚项如下面公式:

其中\alpha是权重函数,而\nu用来度量长宽比的相似性,定义为

 完整的CIOU损失函数定义:

4.2 CIOU代码

def bbox_overlaps_ciou(bboxes1, bboxes2):
    rows = bboxes1.shape[0]
    cols = bboxes2.shape[0]
    cious = torch.zeros((rows, cols))
    if rows * cols == 0:
        return cious
    exchange = False
    if bboxes1.shape[0] > bboxes2.shape[0]:
        bboxes1, bboxes2 = bboxes2, bboxes1
        cious = torch.zeros((cols, rows))
        exchange = True

    w1 = bboxes1[:, 2] - bboxes1[:, 0]
    h1 = bboxes1[:, 3] - bboxes1[:, 1]
    w2 = bboxes2[:, 2] - bboxes2[:, 0]
    h2 = bboxes2[:, 3] - bboxes2[:, 1]

    area1 = w1 * h1
    area2 = w2 * h2

    center_x1 = (bboxes1[:, 2] + bboxes1[:, 0]) / 2
    center_y1 = (bboxes1[:, 3] + bboxes1[:, 1]) / 2
    center_x2 = (bboxes2[:, 2] + bboxes2[:, 0]) / 2
    center_y2 = (bboxes2[:, 3] + bboxes2[:, 1]) / 2

    inter_max_xy = torch.min(bboxes1[:, 2:],bboxes2[:, 2:])
    inter_min_xy = torch.max(bboxes1[:, :2],bboxes2[:, :2])
    out_max_xy = torch.max(bboxes1[:, 2:],bboxes2[:, 2:])
    out_min_xy = torch.min(bboxes1[:, :2],bboxes2[:, :2])

    inter = torch.clamp((inter_max_xy - inter_min_xy), min=0)
    inter_area = inter[:, 0] * inter[:, 1]
    inter_diag = (center_x2 - center_x1)**2 + (center_y2 - center_y1)**2
    outer = torch.clamp((out_max_xy - out_min_xy), min=0)
    outer_diag = (outer[:, 0] ** 2) + (outer[:, 1] ** 2)
    union = area1+area2-inter_area
    u = (inter_diag) / outer_diag
    iou = inter_area / union
    with torch.no_grad():
        arctan = torch.atan(w2 / h2) - torch.atan(w1 / h1)
        v = (4 / (math.pi ** 2)) * torch.pow((torch.atan(w2 / h2) - torch.atan(w1 / h1)), 2)
        S = 1 - iou
        alpha = v / (S + v)
        w_temp = 2 * w1
    ar = (8 / (math.pi ** 2)) * arctan * ((w1 - w_temp) * h1)
    cious = iou - (u + alpha * ar)
    cious = torch.clamp(cious,min=-1.0,max = 1.0)
    if exchange:
        cious = cious.T
    return cious

5 EIOU

论文链接:Focal and Efficient IOU Loss for Accurate Bounding Box Regression

5.1 为什么提出EIOU 

CIOU Loss虽然考虑了边界框回归的重叠面积、中心点距离、纵横比。但是通过其公式中的v反映的纵横比的差异,而不是宽高分别与其置信度的真实差异,所以有时会阻碍模型有效的优化相似性,于是提出EIOU,它的主要思想是:

  •  一是认为CIoU loss对于长宽比加入loss的设计不太合理,于是将CIoU loss中反应长宽比一致性的部分替换成了分别对于长和宽的一致性loss,形成了EIoU loss。
  •         二是认为不太好的回归样本对回归loss产生了比较大的影响,回归质量相对较好的样本则难以进一步优化,所以论文提出Focal EIoU loss进行回归质量较好和质量较差的样本之间的平衡。

EIOU Loss优点:

  • 1)将纵横比的损失项拆分成预测的宽高分别与最小外接框宽高的差值,加速了收敛提高了回归精度。
  • 2)引入了Focal Loss优化了边界框回归任务中的样本不平衡问题,即减少与目标框重叠较少的大量锚框对BBox 回归的优化贡献,使回归过程专注于高质量锚框。

5.2 EIOU代码

def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False,  EIoU=False, eps=1e-7):
    # Returns the IoU of box1 to box2. box1 is 4, box2 is nx4
    box2 = box2.T

    # Get the coordinates of bounding boxes
    if x1y1x2y2:  # x1, y1, x2, y2 = box1
        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]
    else:  # transform from xywh to xyxy
        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

    # Intersection area
    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)

    # Union Area
    w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1 + eps
    w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1 + eps
    union = w1 * h1 + w2 * h2 - inter + eps

    iou = inter / union
    if GIoU or DIoU or CIoU or EIoU:
        cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1)  # convex (smallest enclosing box) width
        ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, b2_y1)  # convex height
        if CIoU or DIoU or EIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
            c2 = cw ** 2 + ch ** 2 + eps  # convex diagonal squared
            rho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 +
                    (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4  # center distance squared
            if DIoU:
                return iou - rho2 / c2  # DIoU
            elif CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
                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))
                return iou - (rho2 / c2 + v * alpha)  # CIoU
            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
                ch2 = ch ** 2 + eps
                return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2)
        else:  # GIoU https://arxiv.org/pdf/1902.09630.pdf
            c_area = cw * ch + eps  # convex area
            return iou - (c_area - union) / c_area  # GIoU
    else:
        return iou  # IoU

6 Wise-IoU

论文链接:Wise-IoU: Bounding Box Regression Loss with Dynamic Focusing Mechanism

具体关于Wise-IoU损失的介绍请参考前期博客

优化改进YOLOv5算法之Wise-IOU损失函数_yolov5算法优化_AI追随者的博客-CSDN博客

7 YOLOv5中添加GIoU、DIoU、CIoU、EIoU、Wise-IoU损失函数

 yolov5-6.1版本中的iou损失函数是在utils/metrics.py文件定义的,在该文件添加以下关于GIoU、DIoU、CIoU、EIoU、Wise-IoU函数的代码,如下所示

import numpy as np
import torch, math
 
class WIoU_Scale:
    ''' monotonous: {
            None: origin v1
            True: monotonic FM v2
            False: non-monotonic FM v3
        }
        momentum: The momentum of running mean'''
    
    iou_mean = 1.
    monotonous = False
    _momentum = 1 - 0.5 ** (1 / 7000)
    _is_train = True
 
    def __init__(self, iou):
        self.iou = iou
        self._update(self)
    
    @classmethod
    def _update(cls, self):
        if cls._is_train: cls.iou_mean = (1 - cls._momentum) * cls.iou_mean + \
                                         cls._momentum * self.iou.detach().mean().item()
    
    @classmethod
    def _scaled_loss(cls, self, gamma=1.9, delta=3):
        if isinstance(self.monotonous, bool):
            if self.monotonous:
                return (self.iou.detach() / self.iou_mean).sqrt()
            else:
                beta = self.iou.detach() / self.iou_mean
                alpha = delta * torch.pow(gamma, beta - delta)
                return beta / alpha
        return 1
    
 
def bbox_iou(box1, box2, xywh=True, GIoU=False, DIoU=False, CIoU=False, SIoU=False, EIoU=False, WIoU=False, Focal=False, alpha=1, gamma=0.5, scale=False, eps=1e-7):
    # Returns Intersection over Union (IoU) of box1(1,4) to box2(n,4)
 
    # Get the coordinates of bounding boxes
    if xywh:  # transform from xywh to xyxy
        (x1, y1, w1, h1), (x2, y2, w2, h2) = box1.chunk(4, -1), box2.chunk(4, -1)
        w1_, h1_, w2_, h2_ = w1 / 2, h1 / 2, w2 / 2, h2 / 2
        b1_x1, b1_x2, b1_y1, b1_y2 = x1 - w1_, x1 + w1_, y1 - h1_, y1 + h1_
        b2_x1, b2_x2, b2_y1, b2_y2 = x2 - w2_, x2 + w2_, y2 - h2_, y2 + h2_
    else:  # x1, y1, x2, y2 = box1
        b1_x1, b1_y1, b1_x2, b1_y2 = box1.chunk(4, -1)
        b2_x1, b2_y1, b2_x2, b2_y2 = box2.chunk(4, -1)
        w1, h1 = b1_x2 - b1_x1, (b1_y2 - b1_y1).clamp(eps)
        w2, h2 = b2_x2 - b2_x1, (b2_y2 - b2_y1).clamp(eps)
 
    # Intersection area
    inter = (b1_x2.minimum(b2_x2) - b1_x1.maximum(b2_x1)).clamp(0) * \
            (b1_y2.minimum(b2_y2) - b1_y1.maximum(b2_y1)).clamp(0)
 
    # Union Area
    union = w1 * h1 + w2 * h2 - inter + eps
    if scale:
        self = WIoU_Scale(1 - (inter / union))
 
    # IoU
    # iou = inter / union # ori iou
    iou = torch.pow(inter/(union + eps), alpha) # alpha iou
    if CIoU or DIoU or GIoU or EIoU or SIoU or WIoU:
        cw = b1_x2.maximum(b2_x2) - b1_x1.minimum(b2_x1)  # convex (smallest enclosing box) width
        ch = b1_y2.maximum(b2_y2) - b1_y1.minimum(b2_y1)  # convex height
        if CIoU or DIoU or EIoU or SIoU or WIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
            c2 = (cw ** 2 + ch ** 2) ** alpha + eps  # convex diagonal squared
            rho2 = (((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 + (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4) ** alpha  # center dist ** 2
            if CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
                v = (4 / math.pi ** 2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2)
                with torch.no_grad():
                    alpha_ciou = v / (v - iou + (1 + eps))
                if Focal:
                    return iou - (rho2 / c2 + torch.pow(v * alpha_ciou + eps, alpha)), torch.pow(inter/(union + eps), gamma)  # Focal_CIoU
                else:
                    return iou - (rho2 / c2 + torch.pow(v * alpha_ciou + eps, alpha))  # CIoU
            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 = torch.pow(cw ** 2 + eps, alpha)
                ch2 = torch.pow(ch ** 2 + eps, alpha)
                if Focal:
                    return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2), torch.pow(inter/(union + eps), gamma) # Focal_EIou
                else:
                    return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2) # EIou
            elif SIoU:
                # SIoU Loss https://arxiv.org/pdf/2205.12740.pdf
                s_cw = (b2_x1 + b2_x2 - b1_x1 - b1_x2) * 0.5 + eps
                s_ch = (b2_y1 + b2_y2 - b1_y1 - b1_y2) * 0.5 + eps
                sigma = torch.pow(s_cw ** 2 + s_ch ** 2, 0.5)
                sin_alpha_1 = torch.abs(s_cw) / sigma
                sin_alpha_2 = torch.abs(s_ch) / sigma
                threshold = pow(2, 0.5) / 2
                sin_alpha = torch.where(sin_alpha_1 > threshold, sin_alpha_2, sin_alpha_1)
                angle_cost = torch.cos(torch.arcsin(sin_alpha) * 2 - math.pi / 2)
                rho_x = (s_cw / cw) ** 2
                rho_y = (s_ch / ch) ** 2
                gamma = angle_cost - 2
                distance_cost = 2 - torch.exp(gamma * rho_x) - torch.exp(gamma * rho_y)
                omiga_w = torch.abs(w1 - w2) / torch.max(w1, w2)
                omiga_h = torch.abs(h1 - h2) / torch.max(h1, h2)
                shape_cost = torch.pow(1 - torch.exp(-1 * omiga_w), 4) + torch.pow(1 - torch.exp(-1 * omiga_h), 4)
                if Focal:
                    return iou - torch.pow(0.5 * (distance_cost + shape_cost) + eps, alpha), torch.pow(inter/(union + eps), gamma) # Focal_SIou
                else:
                    return iou - torch.pow(0.5 * (distance_cost + shape_cost) + eps, alpha) # SIou
            elif WIoU:
                if Focal:
                    raise RuntimeError("WIoU do not support Focal.")
                elif scale:
                    return getattr(WIoU_Scale, '_scaled_loss')(self), (1 - iou) * torch.exp((rho2 / c2)), iou # WIoU https://arxiv.org/abs/2301.10051
                else:
                    return iou, torch.exp((rho2 / c2)) # WIoU v1
            if Focal:
                return iou - rho2 / c2, torch.pow(inter/(union + eps), gamma)  # Focal_DIoU
            else:
                return iou - rho2 / c2  # DIoU
        c_area = cw * ch + eps  # convex area
        if Focal:
            return iou - torch.pow((c_area - union) / c_area + eps, alpha), torch.pow(inter/(union + eps), gamma)  # Focal_GIoU https://arxiv.org/pdf/1902.09630.pdf
        else:
            return iou - torch.pow((c_area - union) / c_area + eps, alpha)  # GIoU https://arxiv.org/pdf/1902.09630.pdf
    if Focal:
        return iou, torch.pow(inter/(union + eps), gamma)  # Focal_IoU
    else:
        return iou  # IoU

然后在utils/loss.py文件中调用bbox_iou损失函数时,将对应的IOU设置为True即可。 

参考文章:【深度学习小知识】目标检测中的IOU、GIOU、DIOU、CIOU、EIOU等理论解析_你好啊:)的博客-CSDN博客 深入浅出Yolo系列之Yolov3&Yolov4&Yolov5&Yolox核心基础知识完整讲解 - 知乎

详解IoU、GIoU、DIoU、CIoU、EIoU和DIoU-NMS_小Aer的博客-CSDN博客

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

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

相关文章

等离子纳秒高压脉冲电源维修HVP-20 P

等离子纳秒高压脉冲电源维修HVP-20 P;HVP-10B;HVP-05;HVP-02等型号均可维修 HVP-20 P(N)用于气体放电与低温等离子体的高性能纳秒高压脉冲电源。 HVP-20P(N)采用专有的marx电路,实现高压脉冲电源参数的便捷可调,包括峰值电压0 – 20 KV (-2…

Go语言容器之map、list和nil

一、map map和C中map一样,里面存放的是key-value键值对在Go中map是引用类型,声明语法:var map变量名 map[key的类型]value的类型package mainimport "fmt"func main() {var mp map[string]intmpls : map[string]int{"one&quo…

不用写代码也能开发,产品经理是怎么做到的?

产品经理再也不用求开发了……就在前几天,我做的小程序上线了! 从产品原型设计,前端开发后端开发,产品部署到运维,都是由我1个人完成的。 我是啥时候学会写代码的呢?不瞒你说,我一行代码都没写…

基于卷积神经网络CNN的甘蔗芽体自动识别,卷积神经网络分类预测

目录 背影 卷积神经网络CNN的原理 卷积神经网络CNN的定义 卷积神经网络CNN的神经元 卷积神经网络CNN的激活函数 卷积神经网络CNN的传递函数 卷积神经网络CNN甘蔗芽体自动识别 基本结构 主要参数 MATALB代码 结果图 展望 背影 现在生活,为节能减排,减少…

LauterBach使用教程

工作需要,使用到劳得巴赫,但是公司只买了调试器,却没有买教程,所以就只能自己摸索和网上搜索这两种途径来学习。 注意:lauterbach可以使用命令来操作,但是由于本人刚刚使用,目前基本上使用的都…

[考前冲刺]计算机三级网络技术复习知识点总结·计算机三级网络技术重难点考前冲刺和解题技巧

选择题第一章重难点一、网络层次结构的功能①核心交换层的基本功能:1、核心交换层将多个汇聚层连接起来,为汇聚层的网络提供高速转发,为整个城域网提供一个高速、安全与具有QoS保障能力的数据传输环境;2、核心交换层实现与主干网络…

2023最新版会声会影更新下载及功能介绍

会声会影(Corel VideoStudio)为加拿大Corel发布的一款功能丰富的视频编辑软件。会声会影2023简单易用,具有史无前例的强大功能,拖放式标题、转场、覆叠和滤镜,色彩分级、动态分屏视频和新增强的遮罩创建器,…

Nuxt项目配置、目录结构说明-实战教程基础-Day02

Nuxt项目配置、目录结构说明-实战教程基础-Day02一、Nuxt项目结构1.1资源目录1.2 组件目录1.3 布局目录1.4 中间件目录1.5 页面目录1.6 插件目录1.7 静态文件目录1.8 Store 目录1.9 nuxt.config.js 文件1.10 package.json 文件其他:别名二、项目配置2.1 build2.2 cs…

0108检测环-无向图-数据结构和算法(Java)

文章目录1 API2 实现和分析3 测试后记1 API 检测一幅图是否还有环&#xff0c;如果有找出环路&#xff08;任意一条&#xff09;&#xff0c;API如下&#xff1a; public classCycleCycle(Grpah G)预处理函数booleanhasCycle()Iterable<Interge>cycle()有环给出环路&am…

用友开发者中心应用构建实践指引!

基于 iuap 技术底座&#xff0c;用友开发者中心致力于为企业和开发者提供一站式技术服务&#xff0c;让人人都能轻松构建企业级应用。 本文以人力资源领域常用的应聘人员信息登记与分析功能为例&#xff0c;详细介绍如何在用友开发者中心使用 YonBuilder 进行应用构建。 功能…

计算机操作系统--哈工大(2)

操作系统的那棵树 本来看着网课是20个小时&#xff0c;还自以为是想着几周学完&#xff0c;是我太自大了&#xff0c;被现实狠狠殴打CPU调度策略如何让进程满意总原则&#xff1a;系统专注于任务执行又能合理调配任务前台任务关注响应时间&#xff0c;后台任务关注周转时间各种…

【C++】C++11新特性——右值引用

文章目录一、左值引用、 右值引用1.1 左值与右值1.2 左值引用1.3 右值引用二、右值引用的意义三、移动语句3.1 移动构造3.2 移动赋值3.3 总结四、move问题五、完美转发5.1 万能引用与折叠5.2 完美转发std::forward一、左值引用、 右值引用 1.1 左值与右值 我们经常能听到左值…

服务搭建篇(九) 使用GitLab+Jenkins搭建CI\CD执行环境 (上) 基础环境搭建

1.前言 每当我们程序员开发在本地完成开发之后 , 都要部署到正式环境去使用 , 在一些传统的运维体系中 , 开发与运维都是割裂的 , 开发人员不允许操作正式服务器 , 服务器只能通过运维团队来操作 , 这样可以极大的提高服务器的安全性 , 不经过安全保护的开放服务器 , 对于黑客…

6、DDIM

简介 去噪扩散概率模型(DDPM)在没有对抗性训练的情况下已经实现了高质量的图像生成&#xff0c;但它们需要模拟马尔可夫链许多步骤才能生成样本。 例如&#xff0c;从DDPM采样50k张大小为32 32的图像需要大约20个小时&#xff0c;而从Nvidia 2080 Ti GPU上的GAN采样则需要不…

Vue:(三十五)路由vue-router

今天&#xff0c;我们开始学习vue中一个很关键的知识点&#xff0c;路由。理解vue的一个插件库&#xff0c;专门用来实现SPA应用单页web应用整个应用只有一个完整的页面点击页面中的导航连接不会刷新页面&#xff0c;只会做页面的局部更新数据需要通过ajax请求获取下来&#xf…

css制作动画(动效的序列帧图)

相信 animation 大家都用过很多&#xff0c;知道是 CSS3做动画用的。而我自己就只会在 X/Y轴 上做位移旋转&#xff0c;使用 animation-timing-function 规定动画的速度曲线&#xff0c;常用到的 贝塞尔曲线。但是这些动画效果都是连续性的。 今天发现个新功能 animation-timi…

【C语言】详讲qsort库函数

qsort函数介绍具体作用qsort函数是一种用于对不同类型数据进行快速排序的函数&#xff0c;排序算法有很多最常用的冒泡排序法仅仅只能对整形进行排序,qsort不同,排序类型不受限制,qsort函数的底层原理是一种快速排序.基本构造qsort( void* arr, int sz, int sizeof, cmp_code);…

【毕业设计】基于Java的五子棋游戏的设计(源代码+论文)

简介 五子棋作为一个棋类竞技运动&#xff0c;在民间十分流行&#xff0c;为了熟悉五子棋规则及技巧&#xff0c;以及研究简单的人工智能&#xff0c;决定用Java开发五子棋游戏。主要完成了人机对战和玩家之间联网对战2个功能。网络连接部分为Socket编程应用&#xff0c;客户端…

IP协议+以太网协议

在计算机网络体系结构的五层协议中&#xff0c;第三层就是负责建立网络连接&#xff0c;同时为上层提供服务的一层&#xff0c;网络层协议主要负责两件事&#xff1a;即地址管理和路由选择&#xff0c;下面就网络层的重点协议做简单介绍~~ IP协议 网际协议IP是TCP/IP体系中两…

20230310英语学习

Some Narcissists Chase Status, Others Want to Win Admiration 自恋并非自尊心膨胀&#xff0c;那它因何而来&#xff1f; Narcissists often rub their friends and family the wrong way by bragging about their exploits, seemingly a symptom of an overinflated sense …