yolov5边界框回归
时间: 2024-12-27 14:13:32 浏览: 99
### YOLOv5 中边界框回归实现方法
在YOLOv5中,边界框回归通过预测目标物体的位置和大小来精确定位图像中的对象。具体来说,模型会预测每个候选区域内的边界框参数,这些参数用于描述边界框相对于预定义锚点(anchor box)的调整。
#### 预测偏移量与sigmoid函数的应用
对于每一个网格单元格,如果该位置存在目标,则需要计算其真实边界框相对应于网络输出特征图上的对应位置[^2]。为了确保预测出来的中心点仍然位于当前负责预测此ground truth box 的cell内部,采用了sigmoid 函数对tx 和 ty 进行变换:
\[ bx = σ(tx) + cx \]
\[ by = σ(ty) + cy \]
其中\( (cx, cy) \)表示grid cell 左上角坐标的归一化值;而 \( tx \), \( ty \) 则是从卷积层得到未经缩放的预测值。经过上述操作后可以保证最终获得的目标框中心坐标始终处于合理的范围之内[^4]。
#### 宽高比例预测
除了定位中心外,还需要估计宽度 w 和高度 h 。这里同样引入了指数运算以保持尺度不变性并防止负数出现:
\[ bw = pw * e^{tw} \]
\[ bh = ph * e^{th} \]
这里的pw/ph代表预先设定好的基础尺寸(anchor size),即不同scale下的初始猜测;tw/th则是由神经网络产生的log-space scale factor ,用来微调原始的比例关系。
#### 损失函数优化
为了让模型更好地学习如何准确地拟合真实的边界框,在训练过程中通常会选择合适的损失度量方式。相较于传统的均方误差(MSE Loss),DIoU loss 或者 CIoU loss 更加适合解决此类问题,因为它们不仅考虑到了两个矩形之间的重叠程度(IOU),还额外加入了形状相似性和距离惩罚项等因素,从而提高了检测精度[^3]。
```python
import torch.nn.functional as F
def diou_loss(pred_boxes, target_boxes):
"""
计算 DIoU 损失
参数:
pred_boxes: 形状为[N, 4]的张量,包含预测边框(xmin,ymin,xmax,ymax)
target_boxes: 同pred_boxes
返回:
平均每条记录对应的DIoU损失
"""
# 获取边框四个顶点坐标
b1_x1, b1_y1, b1_x2, b1_y2 = pred_boxes[:, 0], pred_boxes[:, 1], \
pred_boxes[:, 2], pred_boxes[:, 3]
b2_x1, b2_y1, b2_x2, b2_y2 = target_boxes[:, 0], target_boxes[:, 1], \
target_boxes[:, 2], target_boxes[:, 3]
# 计算交集面积
inter_rect_x1 = torch.max(b1_x1, b2_x1)
inter_rect_y1 = torch.max(b1_y1, b2_y1)
inter_rect_x2 = torch.min(b1_x2, b2_x2)
inter_rect_y2 = torch.min(b1_y2, b2_y2)
inter_area = torch.clamp(inter_rect_x2 - inter_rect_x1 + 1e-16, min=0.) *\
torch.clamp(inter_rect_y2 - inter_rect_y1 + 1e-16, min=0.)
# 计算各自边框面积以及总覆盖区域
b1_area = (b1_x2 - b1_x1 + 1e-16) * (b1_y2 - b1_y1 + 1e-16)
b2_area = (b2_x2 - b2_x1 + 1e-16) * (b2_y2 - b2_y1 + 1e-16)
union_area = b1_area + b2_area - inter_area
ious = inter_area / union_area
# 外接最小矩形C
enclose_left_up = torch.min(b1_x1, b2_x1).unsqueeze(-1), torch.min(b1_y1, b2_y1).unsqueeze(-1)
enclose_right_down = torch.max(b1_x2, b2_x2).unsqueeze(-1), torch.max(b1_y2, b2_y2).unsqueeze(-1)
c_w = enclose_right_down[0] - enclose_left_up[0]
c_h = enclose_right_down[1] - enclose_left_up[1]
outer_diagonal_line_square = c_w ** 2 + c_h ** 2
center_distance_square = ((b1_x1 + b1_x2)/2 - (b2_x1 + b2_x2)/2)**2 + \
((b1_y1 + b1_y2)/2 - (b2_y1 + b2_y2)/2)**2
dious = ious - center_distance_square / outer_diagonal_line_square
return 1 - dious.mean()
```
阅读全文
相关推荐


















