一、本文介绍
本文记录的是改进YOLOv9的损失函数,将其替换成Shape-IoU
。现有边界框回归方法通常考虑GT(Ground Truth)框与预测框之间的几何关系,通过边界框的相对位置和形状计算损失,但忽略了边界框本身的形状和尺度等固有属性对边界框回归的影响。为了弥补现有研究的不足,Shape-IoU
提出了一种关注边界框本身形状和尺度的边界框回归方法。
文章目录
二、Shape-IoU设计原理
Shape-IoU
:考虑边界框形状和尺度的更精确度量
以下是关于Shape-IoU
的详细介绍:
2.1 原理
- 分析边界框回归特性:通过对边界框回归样本的分析,得出以下结论:
- 当回归样本的偏差和形状偏差相同且不全为0时,假设
GT
框不是正方形且有长短边,边界框形状和尺度的差异会导致其IoU值的差异。 - 对于相同尺度的边界框回归样本,当回归样本的偏差和形状偏差相同且不全为0时,边界框的形状会对回归样本的IoU值产生影响。沿着边界框短边方向的偏差和形状偏差对应的IoU值变化更为显著。
- 对于具有相同形状边界框的回归样本,当回归样本偏差和形状偏差相同且不全为0时,与较大尺度的回归样本相比,较小尺度边界框回归样本的
IoU
值受GT
框形状的影响更为显著。
- 当回归样本的偏差和形状偏差相同且不全为0时,假设
- Shape - IoU公式:
- I o U = ∣ B ∩ B g t ∣ ∣ B ∪ B g t ∣ IoU = \frac{|B \cap B^{gt}|}{|B \cup B^{gt}|} IoU=∣B∪Bgt∣∣B∩Bgt∣
- w w = 2 × ( w g t ) s c a l e ( w g t ) s c a l e + ( h g t ) s c a l e ww = \frac{2 \times (w^{gt})^{scale}}{(w^{gt})^{scale} + (h^{gt})^{scale}} ww=(wgt)scale+(hgt)scale2×(wgt)scale
- h h = 2 × ( h g t ) s c a l e ( w g t ) s c a l e + ( h g t ) s c a l e hh = \frac{2 \times (h^{gt})^{scale}}{(w^{gt})^{scale} + (h^{gt})^{scale}} hh=(wgt)scale+(hgt)scale2×(hgt)scale
- d i s t a n c e s h a p e = h h × ( x c − x c g t c ) 2 + w w × ( y c − y c g t c ) 2 distance^{shape} = hh \times (\frac{x_c - x_c^{gt}}{c})^{2} + ww \times (\frac{y_c - y_c^{gt}}{c})^{2} distanceshape=hh×(cxc−xcgt)2+ww×(cyc−ycgt)2
- Ω s h a p e = ∑ t = w , h ( 1 − e − ω t ) θ , θ = 4 \Omega^{shape} = \sum_{t = w, h}(1 - e^{-\omega_t})^{\theta}, \theta = 4 Ωshape=∑t=w,h(1−e−ωt)θ,θ=4,其中 { ω w = h h × ∣ w − w g t ∣ m a x ( w , w g t ) ω h = w w × ∣ h − h g t ∣ m a x ( h , h g t ) \left\{\begin{array}{l} \omega_{w} = hh \times \frac{|w - w^{gt}|}{max(w, w^{gt})} \\ \omega_{h} = ww \times \frac{|h - h^{gt}|}{max(h, h^{gt})} \end{array}\right. {ωw=hh×max(w,wgt)∣w−wgt∣ωh=ww×max(h,hgt)∣h−hgt∣
- 对应的边界框回归损失: L S h a p e − I o U = 1 − I o U + d i s t a n c e s h a p e + 0.5 × Ω s h a p e L_{Shape - IoU} = 1 - IoU + distance^{shape} + 0.5 \times \Omega^{shape} LShape−IoU=1−IoU+distanceshape+0.5×Ωshape
2.2 优势
- 提高检测性能:论文中通过一系列对比实验,证明了
Shape-IoU
方法在不同检测任务中能够有效提高检测性能,优于现有方法,在不同检测任务中达到了最先进的性能。 - 关注边界框自身属性:考虑了边界框本身的形状和尺度对边界框回归的影响,弥补了现有研究忽略这一因素的不足。
- 在小目标检测任务中的应用:针对小目标检测任务,提出了
Shape-Dot Distance
和Shape-NWD
,将Shape-IoU
的思想融入其中,提高了在小目标检测方面的性能。
论文:https://arxiv.org/pdf/2312.17663
源码:https://github.com/malagoutou/Shape-IoU
三、Shape-IoU的实现代码
Shape-IoU
的实现代码如下:
def shape_iou(box1, box2, xywh=True, scale=0 eps=1e-7):
(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_
# 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
#Shape-Distance #Shape-Distance #Shape-Distance #Shape-Distance #Shape-Distance #Shape-Distance #Shape-Distance
ww = 2 * torch.pow(w2, scale) / (torch.pow(w2, scale) + torch.pow(h2, scale))
hh = 2 * torch.pow(h2, scale) / (torch.pow(w2, scale) + torch.pow(h2, scale))
cw = torch.max(b1_x2, b2_x2) - torch.min(b1_x1, b2_x1) # convex width
ch = torch.max(b1_y2, b2_y2) - torch.min(b1_y1, b2_y1) # convex height
c2 = cw ** 2 + ch ** 2 + eps # convex diagonal squared
center_distance_x = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2) / 4
center_distance_y = ((b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4
center_distance = hh * center_distance_x + ww * center_distance_y
distance = center_distance / c2
omiga_w = hh * torch.abs(w1 - w2) / torch.max(w1, w2)
omiga_h = ww * 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)
iou = iou - distance - 0.5 * ( shape_cost)
return iou # IoU
四、添加步骤
4.1 修改utils/loss_tal_dual.py
此处需要修改的文件是utils/loss_tal_dual.py
loss_tal_dual.py
中定义了模型的损失函数和计算方法,我们想要加入新的损失函数就只需要将代码放到这个文件内即可。
Slide Loss
添加后如下:
3.2 修改utils\loss_tal_dual.py
utils\loss_tal_dual.py
是损失函数的辅助分支+主分支损失计算文件。
在utils\loss_tal_dual.py
在的引用中添加shape_iou
,然后在102行处修改成如下代码,使模型调用此Shape-IoU
损失函数。
iou = shape_iou(pred_bboxes_pos, target_bboxes_pos)
此时再次训练模型便会使用Shape-IoU
计算模型的损失函数。