共计 1997 个字符,预计需要花费 5 分钟才能阅读完成。
1. 为什么需要 CIoU?
在目标检测任务中,边界框回归的精度直接影响模型的性能。传统的 IoU(Intersection over Union)虽然简单直观,但存在梯度消失的问题——当预测框与真实框没有重叠时,IoU 为 0,无法提供有效的梯度信息。后续提出的 GIoU 和 DIoU 虽然部分解决了这个问题,但在长宽比一致性上仍有不足。

图 1:CIoU 相比 IoU/GIoU/DIoU 的核心改进点(中心点距离 + 长宽比惩罚)
2. CIoU 的数学原理
CIoU 的完整公式如下:
$$
L_{CIoU}=1-IoU+\frac{\rho^2(b,b^{gt})}{c^2}+\alpha v
$$
其中最关键的是长宽比惩罚项:
$$
v=\left(\frac{4}{\pi^2}\right)\left(\arctan\frac{w^{gt}}{h^{gt}}-\arctan\frac{w}{h}\right)^2
$$
- $\rho$ 表示预测框中心点与真实框中心点的欧式距离
- $c$ 是最小外接矩形的对角线长度
- $\alpha$ 是权重系数,控制长宽比惩罚的强度
- $v$ 项通过 arctan 变换将宽高比差异转化为角度差,再用平方惩罚
3. PyTorch 实现
import torch
import math
def bbox_ciou(box1, box2):
"""
计算两组边界框之间的 CIoU 损失
box 格式: [x1,y1,x2,y2]或[cx,cy,w,h]
"""
# 转换为中心点 + 宽高表示
if box1.size(-1) == 4:
b1_cx = (box1[..., 0] + box1[..., 2]) / 2
b1_cy = (box1[..., 1] + box1[..., 3]) / 2
b1_w = box1[..., 2] - box1[..., 0]
b1_h = box1[..., 3] - box1[..., 1]
b2_cx = (box2[..., 0] + box2[..., 2]) / 2
b2_cy = (box2[..., 1] + box2[..., 3]) / 2
b2_w = box2[..., 2] - box2[..., 0]
b2_h = box2[..., 3] - box2[..., 1]
else:
b1_cx, b1_cy, b1_w, b1_h = box1[..., 0], box1[..., 1], box1[..., 2], box1[..., 3]
b2_cx, b2_cy, b2_w, b2_h = box2[..., 0], box2[..., 1], box2[..., 2], box2[..., 3]
# 计算 IoU
inter = (torch.min(b1_w, b2_w) * torch.min(b1_h, b2_h)).clamp(0)
union = b1_w * b1_h + b2_w * b2_h - inter + 1e-7
iou = inter / union
# 计算中心点距离惩罚
center_distance = (b1_cx - b2_cx)**2 + (b1_cy - b2_cy)**2
c = (torch.max(b1_w, b2_w)**2 + torch.max(b1_h, b2_h)**2).clamp(1e-7)
rho = center_distance / c
# 计算长宽比一致性项
v = (4 / (math.pi ** 2)) * torch.pow(torch.atan(b2_w / b2_h) - torch.atan(b1_w / b1_h), 2)
alpha = v / ((1 - iou) + v + 1e-7)
# 组合成 CIoU
ciou = 1 - iou + rho + alpha * v
return ciou.mean()
在 YOLOv5 中替换损失函数的方法(以 v6.0 版本为例):
- 在
loss.py中找到ComputeLoss类 - 修改
__call__方法中的 bbox 损失计算部分 - 将默认的 GIoU 计算替换为我们的 CIoU 实现
4. 实验对比
在 COCO val2017 数据集上的对比结果:
| 方法 | AP50 | AP75 | mAP |
|---|---|---|---|
| IoU | 45.2 | 24.1 | 28.3 |
| GIoU | 47.1 | 26.5 | 30.1 |
| DIoU | 48.3 | 27.8 | 31.4 |
| CIoU | 49.4 | 28.9 | 32.5 |
图 2:不同 IoU 变体的训练损失曲线对比
5. 避坑指南
- 小目标检测:当处理小目标时,建议降低 $\alpha$ 值(如 0.3-0.5),避免长宽比惩罚过强
- 多尺度训练:在大 batch size 训练时,建议对 $v$ 项做梯度裁剪(如
v.clamp(max=0.5)) - 初始化问题:在训练初期,预测框可能非常不准确,可以给 $v$ 项设置上限(如
v = v.clamp(max=1.0))
6. 总结与思考
CIoU 通过引入中心点距离和长宽比惩罚,显著提升了边界框回归的精度。在实际应用中:
- 对于旋转目标检测,可以考虑将角度差作为第四项加入惩罚
- 与 Focal Loss 结合时,需要注意两者的权重平衡,避免梯度冲突
- 在实时性要求高的场景,可以适当简化 $v$ 项的计算
思考题:
1. 在旋转目标检测中,如何扩展 CIoU 公式?
2. 当 CIoU 与 Focal Loss 结合时,需要注意哪些调参技巧?
正文完
发表至: 未分类
近三天内
