当前位置:   article > 正文

YOLOv5修改Focal EIOU Loss_yolov5改进-添加focaleiou

yolov5改进-添加focaleiou

系列文章目录

YOLOv5修改Focal EIOU Loss

文章目录


前言

CIoU Loss虽然考虑了边界框回归的重叠面积、中心点距离、高宽比。但是其公式中的v反映的是高宽的差异,而不是高宽分别与其置信度的真实差异。因此,有时会阻碍模型有效的优化相似性。针对这一问题,本文在CIoU的基础上将高宽比拆开,提出了EIoU Loss,并且引入了Focal Loss聚焦优质的锚框。

文章贡献:

将高宽比的损失项拆分成预测的高宽分别与最小外接框高宽的差值,加快了收敛速度,提高了回归精度;
引入了Focal Loss,优化了边界框回归任务中的样本不平衡问题,即减少了与目标边界框重叠程度较低的锚框对BBox回归的优化贡献,使回归过程更专注于高质量的锚框。
对合成数据和真实数据进行了广泛的实验。出色的实验结果验证了所提出方法的优越性。详细的消融实验显示了损失函数和参数值不同设置的影响。

考虑到预测目标边界框回归的过程中存在训练样本不平衡的问题,即在一张图像中,回归误差小的高质量锚框数量远少于误差大的低质量锚框数量。质量较差的锚框会产生过大的梯度,影响训练过程。直接使用EIoU Loss效果并不好,所以作者结合Focal Loss提出了Focal-EIoU Loss,从梯度的角度出发,把高质量的锚框和低质量的锚框分开


一、修改两处

1.修改metrics.py

代码如下(示例):

  1. def bbox_iou(box1, box2, xywh=True, GIoU=False, DIoU=False, CIoU=False, SIoU=False, EIoU=False, Focal=False, alpha=1, gamma=0.5, eps=1e-7):
  2.     # Returns Intersection over Union (IoU) of box1(1,4) to box2(n,4)
  3.     # Get the coordinates of bounding boxes
  4.     if xywh:  # transform from xywh to xyxy
  5.         (x1, y1, w1, h1), (x2, y2, w2, h2) = box1.chunk(4, -1), box2.chunk(4, -1)
  6.         w1_, h1_, w2_, h2_ = w1 / 2, h1 / 2, w2 / 2, h2 / 2
  7.         b1_x1, b1_x2, b1_y1, b1_y2 = x1 - w1_, x1 + w1_, y1 - h1_, y1 + h1_
  8.         b2_x1, b2_x2, b2_y1, b2_y2 = x2 - w2_, x2 + w2_, y2 - h2_, y2 + h2_
  9.     else:  # x1, y1, x2, y2 = box1
  10.         b1_x1, b1_y1, b1_x2, b1_y2 = box1.chunk(4, -1)
  11.         b2_x1, b2_y1, b2_x2, b2_y2 = box2.chunk(4, -1)
  12.         w1, h1 = b1_x2 - b1_x1, (b1_y2 - b1_y1).clamp(eps)
  13.         w2, h2 = b2_x2 - b2_x1, (b2_y2 - b2_y1).clamp(eps)
  14.     # Intersection area
  15.     inter = (b1_x2.minimum(b2_x2) - b1_x1.maximum(b2_x1)).clamp(0) * \
  16.             (b1_y2.minimum(b2_y2) - b1_y1.maximum(b2_y1)).clamp(0)
  17.     # Union Area
  18.     union = w1 * h1 + w2 * h2 - inter + eps
  19.     # IoU
  20.     # iou = inter / union # ori iou
  21.     iou = torch.pow(inter/(union + eps), alpha) # alpha iou
  22.     if CIoU or DIoU or GIoU or EIoU or SIoU:
  23.         cw = b1_x2.maximum(b2_x2) - b1_x1.minimum(b2_x1)  # convex (smallest enclosing box) width
  24.         ch = b1_y2.maximum(b2_y2) - b1_y1.minimum(b2_y1)  # convex height
  25.         if CIoU or DIoU or EIoU or SIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1
  26.             c2 = (cw ** 2 + ch ** 2) ** alpha + eps  # convex diagonal squared
  27.             rho2 = (((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 + (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4) ** alpha  # center dist ** 2
  28.             if CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
  29.                 v = (4 / math.pi ** 2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2)
  30.                 with torch.no_grad():
  31.                     alpha_ciou = v / (v - iou + (1 + eps))
  32.                 if Focal:
  33.                     return iou - (rho2 / c2 + torch.pow(v * alpha_ciou + eps, alpha)), torch.pow(inter/(union + eps), gamma)  # Focal_CIoU
  34.                 else:
  35.                     return iou - (rho2 / c2 + torch.pow(v * alpha_ciou + eps, alpha))  # CIoU
  36.             elif EIoU:
  37.                 rho_w2 = ((b2_x2 - b2_x1) - (b1_x2 - b1_x1)) ** 2
  38.                 rho_h2 = ((b2_y2 - b2_y1) - (b1_y2 - b1_y1)) ** 2
  39.                 cw2 = torch.pow(cw ** 2 + eps, alpha)
  40.                 ch2 = torch.pow(ch ** 2 + eps, alpha)
  41.                 if Focal:
  42.                     return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2), torch.pow(inter/(union + eps), gamma) # Focal_EIou
  43.                 else:
  44.                     return iou - (rho2 / c2 + rho_w2 / cw2 + rho_h2 / ch2) # EIou
  45.             elif SIoU:
  46.                 # SIoU Loss https://arxiv.org/pdf/2205.12740.pdf
  47.                 s_cw = (b2_x1 + b2_x2 - b1_x1 - b1_x2) * 0.5 + eps
  48.                 s_ch = (b2_y1 + b2_y2 - b1_y1 - b1_y2) * 0.5 + eps
  49.                 sigma = torch.pow(s_cw ** 2 + s_ch ** 2, 0.5)
  50.                 sin_alpha_1 = torch.abs(s_cw) / sigma
  51.                 sin_alpha_2 = torch.abs(s_ch) / sigma
  52.                 threshold = pow(2, 0.5) / 2
  53.                 sin_alpha = torch.where(sin_alpha_1 > threshold, sin_alpha_2, sin_alpha_1)
  54.                 angle_cost = torch.cos(torch.arcsin(sin_alpha) * 2 - math.pi / 2)
  55.                 rho_x = (s_cw / cw) ** 2
  56.                 rho_y = (s_ch / ch) ** 2
  57.                 gamma = angle_cost - 2
  58.                 distance_cost = 2 - torch.exp(gamma * rho_x) - torch.exp(gamma * rho_y)
  59.                 omiga_w = torch.abs(w1 - w2) / torch.max(w1, w2)
  60.                 omiga_h = torch.abs(h1 - h2) / torch.max(h1, h2)
  61.                 shape_cost = torch.pow(1 - torch.exp(-1 * omiga_w), 4) + torch.pow(1 - torch.exp(-1 * omiga_h), 4)
  62.                 if Focal:
  63.                     return iou - torch.pow(0.5 * (distance_cost + shape_cost) + eps, alpha), torch.pow(inter/(union + eps), gamma) # Focal_SIou
  64.                 else:
  65.                     return iou - torch.pow(0.5 * (distance_cost + shape_cost) + eps, alpha) # SIou
  66.             if Focal:
  67.                 return iou - rho2 / c2, torch.pow(inter/(union + eps), gamma)  # Focal_DIoU
  68.             else:
  69.                 return iou - rho2 / c2  # DIoU
  70.         c_area = cw * ch + eps  # convex area
  71.         if Focal:
  72.             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
  73.         else:
  74.             return iou - torch.pow((c_area - union) / c_area + eps, alpha)  # GIoU https://arxiv.org/pdf/1902.09630.pdf
  75.     if Focal:
  76.         return iou, torch.pow(inter/(union + eps), gamma)  # Focal_IoU
  77.     else:
  78.         return iou  # IoU

2.修改loss.py

代码如下(示例):

  1. iou = bbox_iou(pbox, tbox[i], CIoU=True)  # iou(prediction, target)
  2. if type(iou) is tuple:
  3.     lbox += (iou[1].detach().squeeze() * (1 - iou[0].squeeze())).mean()
  4.     iou = iou[0].squeeze()
  5. else:
  6.     lbox += (1.0 - iou.squeeze()).mean()  # iou loss
  7.     iou = iou.squeeze()


最后修改参数就在调用bbox_iou中进行修改即可,比如上面的代码就是使用了CIoU,如果你想使用Focal_EIoU那么你可以修改为下:

iou = bbox_iou(pbox, tbox[i], EIoU=True, Focal=True


 

大家可以试着修改一下

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/402630
推荐阅读
相关标签
  

闽ICP备14008679号