【参考文档】江大白的yolo解析
后面会给出我的完整代码,先来分段看看!
转化格式
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
转换成这种格式:
文章图片
IOU 这个应该都很熟了
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)
#.clamp:将小于0的元素修改为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 + ep
iou = inter / union
clamp
def clamp(self, min: _float=-inf, max: _float=inf, *, out: Optional[Tensor]=None) -> Tensor: ...
inf:无穷大
-inf:负无穷
out:输出,默认即可,不用设定
在 yolov5的使用中,应该是截断掉小于0的部分
(torch.min(b1_x2, b2_x2) - torch.max(b1_x1, b2_x1)).clamp(0)
torch.clamp
DIOU 在正式进入各种iou之前
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)# 最小包裹矩形高度
cw :最小外包矩形宽度
ch :最小外包矩形高度
文章图片
分子部分的一次项代表:GT框和bbox框中心点的距离
c:两个框对角线的距离
文章图片
考虑了重叠面积和中心点距离
c2 = cw ** 2 + ch ** 2 + eps# 勾股定理,使用两边的平方和来代替斜边的平方
rho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 +
(b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4
if DIoU:
return iou - rho2 / c2# DIoU
c2: 勾股定理,使用两边的平方和来代替斜边的平方
GIOU
文章图片
c_area = cw * ch + eps# convex area
return iou - (c_area - union) / c_area# GIoU
CIoU CIOU_Loss和DIOU_Loss前面的公式都是一样的,不过在此基础上还增加了一个影响因子,将预测框和目标框的长宽比都考虑了进去。
文章图片
其中v是衡量长宽比一致性的参数,我们也可以定义为:
文章图片
这样CIOU_Loss就将目标框回归函数应该考虑三个重要几何因素:重叠面积、中心点距离,长宽比全都考虑进去了。
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
EIOU 【参考博文】IOU、GIOU、DIOU、CIOU、EIOU、Focal EIOU、alpha IOU损失函数
前两部分延续CIOU中的方法,但是宽高损失直接使目标盒与锚盒的宽度和高度之差最小,使得收敛速度更快。
文章图片
该损失函数包含三个部分:重叠损失,中心距离损失,宽高损失
rho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 +
(b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4# center distance squared
elif EIoU:
w=(w1-w2)*(w1-w2)
h=(h1-h2)*(h1-h2)
return iou-(rho2/c2+w/(cw**2)+h/(ch**2))
w:宽度差的平方
h:高度差的平方
SIOU 直接看这篇的解析吧。就不重复写了
然后上一下完整代码
def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=False, SIoU=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 + epsiou = inter / union
if GIoU or DIoU or CIoU or SIoU 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 SIoU:# SIoU Loss 2022.08.01
sigma = torch.pow(cw ** 2 + ch ** 2, 0.5)
sin_alpha_1 = ch / sigma
sin_alpha_2 = cw / sigma
threshold = pow(2, 0.5) / 2
sin_alpha = torch.where(sin_alpha_1 > threshold, sin_alpha_2, sin_alpha_1)
# angle_cost = 1 - 2 * torch.pow( torch.sin(torch.arcsin(sin_alpha) - np.pi/4), 2)
angle_cost = torch.cos(torch.arcsin(sin_alpha) * 2 - np.pi / 2)
rho_x = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) / cw) ** 2
rho_y = ((b2_y1 + b2_y2 - b1_y1 - b1_y2) / ch) ** 2
gamma = 2 - angle_cost
distance_cost = 2 - torch.exp(-1 * gamma * rho_x) - torch.exp(-1 * 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)
return iou - 0.5 * (distance_cost + shape_cost)elif 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:
w=(w1-w2)*(w1-w2)
h=(h1-h2)*(h1-h2)
return iou-(rho2/c2+w/(cw**2)+h/(ch**2))#EIOU
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
在yolov5使用方法
1.metrics.py修改一下注释掉原来的bbox_iou,复制上面的完整代码
2.loss.py中把想要使用的iou设置为True(下图以EIOU为例)
【#|yolov5 优化方法(四)修改bbox损失函数(补充EIOU,SIOU)】
文章图片
推荐阅读
- 向前端进军|【没对象怎么办(JavaScript-带你找对象】对象是什么,对象能干嘛,对象该怎么用,本篇带你了解js中的对象。)
- #|TSA优化算法——模仿航海过程中外套的喷气推进和蜂群行为(Matlab代码实现)
- #|基于分布鲁棒优化的电-气-热综合能源系统日前经经济调度
- #|【优化算法】多目标晶体结构算法算法(Matlab代码实现)
- #|基于模糊神经网络算法预测电价(Matlabd代码实现)
- 神经网络|只需两行代码,2080Ti 就能当 V100用,这个炼丹神器真牛!
- 自然语言处理|横扫六大权威榜单后,达摩院开源深度语言模型体系 AliceMind
- 医学影像|Pair 智能标注神器,医生的好帮手
- 人工智能|深蓝学院-多传感器融合定位课程-第3章-3D激光里程计II