目标检测系列—YOLOv1 详解
1. 引言
在计算机视觉领域,目标检测(Object Detection)是一个关键任务,它不仅需要识别图像中的目标类别,还需要定位目标的位置。传统方法(如 R-CNN 系列)虽然在精度上表现优秀,但速度较慢,难以满足实时需求。为了解决这一问题,Joseph Redmon 在 2016 年提出了 YOLO(You Only Look Once)系列,彻底改变了目标检测的范式。
YOLOv1 作为该系列的首个版本,采用端到端的单阶段检测框架,以极高的速度完成目标检测任务。本文将深入解析 YOLOv1 的核心思想、网络架构、损失函数,并提供相关代码示例。
2. YOLOv1 的核心思想
YOLOv1 的核心理念是 “一次看完(You Only Look Once)”,将目标检测任务转换为 回归问题(Regression),直接预测目标的类别和边界框,而不是像 R-CNN 那样依赖候选区域(Region Proposals)。
其主要特点包括:
- 单阶段检测(One-stage):整个网络是一体化的,不需要额外的候选区域生成。
- 全局信息利用:利用整个图像的信息进行检测,而不是仅靠局部信息。
- 速度快:由于采用全卷积网络(Fully Convolutional Network, FCN),YOLOv1 的检测速度大大提升,可达 45 FPS。
3. YOLOv1 的网络结构
YOLOv1 采用一个类似于 GoogLeNet 的 CNN 作为特征提取网络,去掉全连接层,并在最后加上一个用于预测的输出层。
3.1 网络架构
YOLOv1 由 24 个卷积层 + 2 个全连接层组成,核心结构如下:
- 输入层:输入图像大小为 448×448×3448 \times 448 \times 3448×448×3。
- 特征提取部分:使用多个卷积层提取特征,类似 GoogLeNet,但更轻量。
- 输出层:最终输出一个 S×S×(B×5+C)S \times S \times (B \times 5 + C)S×S×(B×5+C) 的张量,其中:
- S×SS \times SS×S:将输入图像划分成 S×SS \times SS×S 个网格(通常是 7×77 \times 77×7)。
- BBB:每个网格预测 BBB 个边界框(YOLOv1 取 B=2B=2B=2)。
- CCC:类别数(如 PASCAL VOC 数据集有 20 类目标)。
3.2 网络输出格式
假设 S=7,B=2,C=20S=7, B=2, C=20S=7,B=2,C=20,那么输出的张量尺寸为 7×7×(2×5+20)=7×7×307 \times 7 \times (2 \times 5 + 20) = 7 \times 7 \times 307×7×(2×5+20)=7×7×30。
其中,每个单元格预测:
- 两个边界框 (x,y,w,h,c)(x, y, w, h, c)(x,y,w,h,c)
- (x,y)(x, y)(x,y):边界框中心相对网格的位置。
- (w,h)(w, h)(w,h):边界框的宽高,相对整个图像归一化。
- ccc:置信度,表示是否包含目标。
- 类别概率 CCC:用于目标分类。
完整的网络结构代码实现如下(基于 PyTorch):
import torch
import torch.nn as nn
class YOLOv1(nn.Module):
def __init__(self, S=7, B=2, C=20):
super(YOLOv1, self).__init__()
self.S, self.B, self.C = S, B, C
self.conv_layers = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3),
nn.LeakyReLU(0.1),
nn.MaxPool2d(kernel_size=2, stride=2),
# 继续添加多个卷积层(省略部分代码)
)
self.fc_layers = nn.Sequential(
nn.Flatten(),
nn.Linear(1024 * S * S, 4096),
nn.LeakyReLU(0.1),
nn.Linear(4096, S * S * (B * 5 + C)),
)
def forward(self, x):
x = self.conv_layers(x)
x = self.fc_layers(x)
return x.view(-1, self.S, self.S, self.B * 5 + self.C)
4. YOLOv1 的损失函数
YOLOv1 采用 均方误差(MSE) 作为损失函数,但针对目标检测任务做了一些修改,包括:
- 边界框损失(Bbox Loss):对预测的 (x,y,w,h)(x, y, w, h)(x,y,w,h) 计算误差,宽高部分使用平方根,以避免小目标对损失的影响。
- 置信度损失(Confidence Loss):置信度衡量边界框是否包含目标,使用 MSE 计算。
- 类别损失(Class Loss):目标的分类损失,采用交叉熵。
代码示例如下:
class YoloLoss(nn.Module):
def __init__(self, S=7, B=2, C=20):
super(YoloLoss, self).__init__()
self.S, self.B, self.C = S, B, C
self.mse = nn.MSELoss()
def forward(self, preds, targets):
# 提取预测值和真实值
pred_boxes = preds[..., :self.B * 5].reshape(-1, self.S, self.S, self.B, 5)
true_boxes = targets[..., :self.B * 5].reshape(-1, self.S, self.S, self.B, 5)
# 计算坐标损失
coord_loss = self.mse(pred_boxes[..., :2], true_boxes[..., :2])
# 计算置信度损失
conf_loss = self.mse(pred_boxes[..., 4], true_boxes[..., 4])
# 计算类别损失
class_loss = self.mse(preds[..., self.B * 5:], targets[..., self.B * 5:])
return coord_loss + conf_loss + class_loss
5. 结论
YOLOv1 作为单阶段检测的开创者,实现了端到端的目标检测,并且大大提高了检测速度。尽管在小目标检测上表现欠佳,但其创新性推动了后续 YOLOv2、YOLOv3 乃至 YOLOv8 的发展。
在下一篇博客中,我们将深入解析 YOLOv2 的改进点,敬请期待!
如果觉得本文对你有帮助,欢迎点赞、收藏并关注! 🚀
24万+

被折叠的 条评论
为什么被折叠?



