yolov8CIoU Loss替代GIOULoss代码
时间: 2025-06-18 19:56:32 浏览: 13
### YOLOv8 使用 CIoU Loss 替代 GIoU Loss 的代码实现
在目标检测任务中,CIoU Loss 是一种改进的损失函数,相较于 GIoU Loss,它考虑了边界框之间的重叠区域、中心点距离以及长宽比的影响。以下是基于 PyTorch 的 YOLOv8 实现中将 CIoU Loss 替代 GIoU Loss 的代码示例。
#### 1. 损失函数定义
CIoU Loss 的核心公式如下:
\[
CIoU = IoU - \frac{d^2}{c^2} - \alpha v
\]
其中:
- \(d\) 是预测框与真实框中心点的距离。
- \(c\) 是包含两个框的最小外接矩形的对角线长度。
- \(v\) 表示长宽比的一致性:\(v = \frac{(ar_{gt} - ar_{pred})^2}{\kappa}\)。
- \(\alpha\) 是一个平衡因子,用于调整 \(v\) 的权重[^1]。
以下是 CIoU Loss 的实现代码:
```python
import torch
def bbox_iou(box1, box2, x1y1x2y2=True, GIoU=False, DIoU=False, CIoU=True, 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 + eps
iou = inter / union
if CIoU or DIoU:
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 CIoU: # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47
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 ** 2
v = (4 / math.pi**2) * torch.pow(torch.atan(w2 / (h2 + eps)) - torch.atan(w1 / (h1 + eps)), 2)
with torch.no_grad():
alpha = v / (v - iou + (1 + eps))
return iou - (rho2 / c2 + v * alpha) # CIoU
elif DIoU:
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 ** 2
return iou - rho2 / c2 # DIoU
return iou # IoU
```
#### 2. 替换 YOLOv8 中的损失函数
YOLOv8 的训练流程通常会定义一个损失函数模块。假设当前使用的是 GIoU Loss,可以将其替换为 CIoU Loss。以下是修改后的代码片段:
```python
class ComputeLoss:
def __init__(self, model):
self.model = model
self.hyp = model.hyp
self.device = next(model.parameters()).device
def __call__(self, preds, targets):
loss_box = torch.zeros(1, device=self.device)
for pred in preds:
# 计算边界框损失
box_loss = self.bbox_loss(pred[:, :4], targets[:, :4])
loss_box += box_loss
return loss_box
def bbox_loss(self, pred_boxes, target_boxes):
return 1 - bbox_iou(pred_boxes.T, target_boxes, x1y1x2y2=False, CIoU=True)
```
#### 3. 训练过程中的调用
在训练过程中,确保 `ComputeLoss` 类被正确初始化并调用。例如:
```python
loss_fn = ComputeLoss(model)
total_loss = loss_fn(preds, targets)
total_loss.backward()
optimizer.step()
```
通过上述代码,YOLOv8 的边界框回归损失从 GIoU Loss 替换为了 CIoU Loss。
---
阅读全文
相关推荐


















