共计 2120 个字符,预计需要花费 6 分钟才能阅读完成。
一、为什么需要 CIoU?
目标检测中的边界框回归就像玩「套圈游戏」:IoU 只关心圈是否套中奖品(重叠区域),但 GIoU 发现圈完全套歪时无法提供改进方向(梯度消失),DIoU 增加了瞄准靶心的距离惩罚。而 CIoU 更进一步——它不仅要求圈要套中奖品、靠近靶心,还要求圈的形状和奖品包装盒匹配(长宽比一致)。

图示:从左到右分别是 IoU、GIoU、DIoU 和 CIoU 的优化效果,注意 CIoU 最终使预测框(蓝色)与真实框(绿色)的长宽比完全一致
二、拆解 CIoU 的数学原理
完整 CIoU 公式看起来有点吓人,但其实可以分三部分理解:
L_{CIoU} = 1 - IoU + \frac{\rho^2(b,b^{gt})}{c^2} + \alpha v
- 基础重叠项(1-IoU):与传统 IoU 一致,衡量两个框的重叠面积
- 中心距离惩罚(第二项):与 DIoU 相同,惩罚预测框与真实框中心点的欧氏距离
- 长宽比惩罚项(αv):CIoU 独有的核心改进,其中最难理解的是 v 的计算:
v = \frac{4}{\pi^2}(\arctan\frac{w^{gt}}{h^{gt}} - \arctan\frac{w}{h})^2
这个式子实际上在做三件事:
- 通过 arctan 将宽高比转换为角度(避免尺度敏感)
- 用角度差衡量形状差异(相比直接计算宽高比更稳定)
- 前面的系数把数值归一化到 [0,1] 范围
三、PyTorch 实现技巧
实际实现时需要特别注意向量化计算,以下是核心代码段:
def bbox_ciou(box1, box2):
"""
box1: 预测框 [...,4] (x1,y1,x2,y2)
box2: 真实框 [...,4] (x1,y1,x2,y2)
返回: CIoU loss [...,]
"""
# 计算交集面积
inter_area = (torch.min(box1[...,2], box2[...,2]) - torch.max(box1[...,0], box2[...,0])).clamp(0) * \
(torch.min(box1[...,3], box2[...,3]) - torch.max(box1[...,1], box2[...,1])).clamp(0)
# 计算 IoU(基础项)union_area = (box1[...,2]-box1[...,0])*(box1[...,3]-box1[...,1]) + \
(box2[...,2]-box2[...,0])*(box2[...,3]-box2[...,1]) - inter_area
iou = inter_area / (union_area + 1e-7)
# 中心点距离惩罚(DIoU 部分)center_dist = torch.pow(box1[...,:2]+box1[...,2:]/2 - (box2[...,:2]+box2[...,2:]/2), 2).sum(-1)
c_diagonal = torch.pow(box1[...,2:].max() - box1[...,:2].min(), 2).sum(-1)
diou_term = center_dist / (c_diagonal + 1e-7)
# 长宽比一致性项(CIoU 核心)arctan = torch.atan2(box2[...,3]-box2[...,1], box2[...,2]-box2[...,0]) - \
torch.atan2(box1[...,3]-box1[...,1], box1[...,2]-box1[...,0])
v = (4 / (math.pi ** 2)) * torch.pow(arctan, 2)
alpha = v / (1 - iou + v + 1e-7)
return 1 - iou + diou_term + alpha * v
四、YOLOv5 中的实战改造
在 YOLOv5 中替换损失函数只需修改 loss.py 中的 ComputeLoss 类:
- 找到
bbox_iou函数调用处 - 替换为我们的
bbox_ciou实现 - 关键配置点:
# data/hyps/hyp.scratch-low.yaml
loss: ciou # 原为 giou
ciou_ratio: 0.05 # 控制长宽比惩罚强度
五、实验结果与调参心得
在 COCO val2017 上的测试数据(YOLOv5s 模型):
| 损失函数 | AP50 | AP75 | 小目标 AP |
|---|---|---|---|
| IoU | 56.1 | 34.2 | 12.3 |
| GIoU | 56.8 | 35.1 | 13.1 |
| DIoU | 57.3 | 35.7 | 13.5 |
| CIoU | 58.2 | 36.8 | 14.4 |
调参经验:
- 小目标检测时建议调低 α(0.01-0.1),因为小目标的长宽比容易受噪声影响
- 多尺度训练时可能出现梯度爆炸,解决方法:
- 对 v 项做梯度裁剪(
torch.nn.utils.clip_grad_norm_) - 采用 warmup 策略逐步增加 α 权重
六、延伸思考
- 旋转目标检测:当前 CIoU 只能处理水平矩形框,可以尝试将角度参数引入 arctan 计算
- 与 Focal Loss 结合:需要注意两者加权方式——Focal Loss 主要解决正负样本不平衡,而 CIoU 优化正样本回归,建议:
- 保持 Focal Loss 的分类权重
- 对 CIoU 项不做类别加权
试想一个场景:检测货架上的书本(长条形)和饮料罐(接近方形)。使用 CIoU 后,模型对书本的检测框会明显变得更 ” 瘦长 ”,这正是长宽比惩罚项起作用的直观体现。
正文完
