YOLOv5改进实战 | 更换损失函数(三)之MPDIOU(2023最新IOU)篇


在这里插入图片描述


前言

本文使用的YOLOv5版本为v7.0,该版本为YOLOv5最新版本,默认损失函数采用的是CIoU。本章节主要介绍如何将MPDIoU损失函数应用于目标检测YOLOv5模型。


🚀🚀🚀 YOLOv5改进损失函数系列:

YOLOv5改进实战(1)| 更换损失函数(一)之EIoU、Alpha-IoU、SIoU篇
YOLOv5改进实战(2)| 更换损失函数(二)之WIOU(Wise IoU)篇
YOLOv5改进实战(3)| 更换损失函数(三)之MPDIOU(2023最新IOU)篇
YOLOv5改进实战(6)| 更换损失函数(四)之NWD(小目标检测)篇


一、MPDIoU

论文链接MPDIoU: A Loss for Efficient and Accurate Bounding Box Regression

MPDIoU是一种基于最小点距离的新型边界框相似度比较度量标准,直接最小化预测边界框与实际标注边界框之间的左上角和右下角点距离。MPDIoU包含了现有损失函数中考虑的所有相关因素,即重叠 或非重叠区域、中心点距离、宽高偏差,同时简化计算过程。
d 1 2 = ( x 1 p r d − x 1 g t ) 2 + ( y 1 p r d − y 1 g t ) 2 d_1^2=\left ( x_1^{prd} -x_1^{gt} \right ) ^2+\left ( y_1^{prd}-y_1^{gt} \right ) ^2 d12=(x1prdx1gt)2+(y1prdy1gt)2

d 2 2 = ( x 2 p r d − x 2 g t ) 2 + ( y 2 p r d − y 2 g t ) 2 d_2^2=\left ( x_2^{prd} -x_2^{gt} \right ) ^2+\left ( y_2^{prd}-y_2^{gt} \right ) ^2 d22=(x2prdx2gt)2+(y2prdy2gt)2

M P D I o U = I O U − d 1 2 w 2 + h 2 − d 2 2 w 2 + h 2 MPDIoU = IOU - \frac{d_1^2}{w^2+h^2} - \frac{d_2^2}{w^2+h^2} MPDIoU=IOUw2+h2d12w2+h2d22
在这里插入图片描述
L M P D I o U = 1 − M P D I o U L_{MPDIoU} = 1 - MPDIoU LMPDIoU=1MPDIoU

二、代码实现

添加损失函数

  1. 更换损失函数主要修改metrics.py文件中的bbox_iou函数
    • 源代码如下:
      def bbox_iou(box1, box2, xywh=True, GIoU=False, DIoU=False, CIoU=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 + eps
             w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1 + eps
      
         # 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
         union = w1 * h1 + w2 * h2 - inter + eps
      
         # IoU
         iou = inter / union
         if CIoU or DIoU or GIoU:
             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:  # 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 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.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
                 return iou - rho2 / c2  # DIoU
             c_area = cw * ch + eps  # convex area
             return iou - (c_area - union) / c_area  # GIoU https://arxiv.org/pdf/1902.09630.pdf
         return iou  # IoU
      
    • 替换成以下代码
      def bbox_iou(box1, box2, xywh=True, GIoU=False, DIoU=False, CIoU=False, MDPIoU=False, hw=None, 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
              w2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1
      
          # 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
          union = w1 * h1 + w2 * h2 - inter + eps
      
          # IoU
          iou = inter / union
          if CIoU or DIoU or GIoU:
              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:  # 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 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.pow(torch.atan(w2 / (h2 + eps)) - torch.atan(w1 / (h1 + eps)), 2)
                      with torch.no_grad():
                          alpha = v / (v - iou + (1 + eps))
                      return iou - (rho2 / c2 + v * alpha)  # CIoU
                  return iou - rho2 / c2  # DIoU
              c_area = cw * ch + eps  # convex area
              return iou - (c_area - union) / c_area  # GIoU https://arxiv.org/pdf/1902.09630.pdf
          elif MDPIoU:
              d1 = (b2_x1 - b1_x1) ** 2 + (b2_y1 - b1_y1) ** 2
              d2 = (b2_x2 - b1_x2) ** 2 + (b2_y2 - b1_y2) ** 2
              return iou - d1 / hw - d2 / hw  # MPDIoU
          return iou  # IoU
      

更换MPDIoU

按照上述更改metrics.py文件中的bbox_iou函数后,在utils/loss.py中,找到ComputeLoss类中的__call__()函数
在这里插入图片描述

# MPDIoU
iou = bbox_iou(pbox, tbox[i], MDPIoU=True, hw=tobj.size()[2] * tobj.size()[3]).squeeze()

在这里插入图片描述

  • 22
    点赞
  • 150
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

w94ghz

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

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

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

打赏作者

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

抵扣说明:

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

余额充值