目标检测与分割
YOLO 系列 / Faster R-CNN 原理、语义分割 U-Net、实例分割 Mask R-CNN
任务定义
在计算机视觉领域,目标检测、语义分割和实例分割是三种核心的图像理解任务,它们既有区别又相互关联。
目标检测(Object Detection) 的任务是定位图像中感兴趣的目标并识别其类别。输出形式为每个目标的边界框(bounding box)及其对应的类别标签和置信度分数。目标检测不关心目标的精确轮廓,只提供一个矩形区域来框住目标。
语义分割(Semantic Segmentation) 对图像中的每个像素赋予一个语义类别标签,将图像划分为多个具有语义意义的区域。语义分割不区分同一类别的不同个体——所有属于"人"类别的像素被归为一类,而不会区分"人A"和"人B"。
实例分割(Instance Segmentation) 结合了目标检测和语义分割:它不仅要对每个像素进行分类,还要区分同一类别的不同实例。输出是每个目标的精确像素级掩码(mask),既知道"这是人",也知道"这是第一个人"。实例分割是三者中难度最高的任务。
三者的共同基础是特征提取(通常使用 CNN 或 Transformer 骨干网络),区别在于输出层的设计和对空间信息的处理粒度不同。
目标检测 — 两阶段方法
两阶段检测器将检测任务分解为"候选区域生成"和"区域分类与精修"两个步骤,代表方法是 Faster R-CNN。
Faster R-CNN
Faster R-CNN 由 Ren 等人于 2015 年提出,是两阶段检测方法的集大成者。它将候选区域生成和后续分类纳入统一的端到端网络。
阶段一:RPN(Region Proposal Network)
RPN 是一个轻量的全卷积网络,在共享卷积特征图上滑动。它在每个滑动位置预定义一组不同尺度、不同长宽比的锚点框(Anchor Box),通常包含 3 种尺度和 3 种长宽比,共计 9 个锚点。RPN 输出两路结果:
- 分类分支:判断每个锚点框是前景(有目标)还是背景
- 回归分支:预测锚点框到真实边界框的偏移量(dx, dy, dw, dh)
RPN 生成的候选区域经过非极大值抑制(NMS)筛选后,约保留 2000 个区域送入第二阶段。
ROI Pooling 与 ROI Align
第二阶段需要对不同尺寸的候选区域提取固定大小的特征。Fast R-CNN 提出的 ROI Pooling 将候选区域划分为固定数量的网格(如 7x7),在每个网格内做最大池化。但 ROI Pooling 存在两次量化误差(从坐标到网格、从网格到特征图位置),这对分类影响不大,但对分割等像素级任务有害。
Mask R-CNN 提出的 ROI Align 解决了这一问题:它取消量化操作,采用双线性插值在每个网格内采样 4 个点,取平均值作为该网格的输出值。ROI Align 使得特征图上的坐标映射保持亚像素精度。
阶段二:分类与回归头
将 ROI Align 输出的固定尺寸特征送入全连接层,分别进行:
- 精细的目标类别分类(使用 Softmax,包含背景类)
- 边界框位置的精细回归
Faster R-CNN 的精度优势来自 RPN 的高质量候选区域和两阶段的逐步精化,但推理速度受限于两阶段串行处理。
目标检测 — 单阶段方法
单阶段检测器直接在网络中一次预测目标的类别和位置,以速度见长,代表是 YOLO 系列。
YOLO 系列演进
YOLOv1(2016) 开创性地将检测视为回归问题:将输入图像划分为 SxS 的网格,每个网格负责预测 B 个边界框和 C 个类别概率。YOLOv1 速度极快但定位精度不足,尤其对小目标检测效果差,且同一网格无法检测多个目标。
YOLOv2(YOLO9000) 引入了锚点框(Anchor Box)、批归一化(Batch Normalization)和多尺度训练,提升了召回率和精度。
YOLOv3(2018) 是一次重大改进:采用 Darknet-53 作为骨干网络,引入 多尺度预测(三个尺度的特征图分别检测大、中、小目标),每个尺度使用 3 个锚点框。YOLOv3 在保持速度优势的同时大幅提升了小目标检测能力,成为工业界广泛使用的版本。
YOLOv4(2020) 集成了大量工程技巧:CSPDarknet53 骨干、Mish 激活函数、PANet 路径聚合、CIoU 损失函数等,在速度和精度上达到当时的最佳平衡。
YOLOv5 至 YOLOv8 由 Ultralytics 团队持续维护优化,侧重于工程化和易用性:
- YOLOv5 提供 n/s/m/l/x 多种模型尺寸,采用自动锚点框学习、数据增强(Mosaic、MixUp)等策略
- YOLOv6(美团)在部署友好性上做了优化,支持更高效的 backbond
- YOLOv7 提出扩展高效层聚合网络(E-ELAN)
- YOLOv8 是目前最成熟的版本,同时支持检测、分割、姿态估计等多种任务,提供统一的训练和推理 API
YOLO 的核心优势在于速度。单阶段结构避免了候选区域生成的额外开销,结合高效的 CSP 和 C2f 模块,YOLOv8 在 NVIDIA T4 GPU 上可实现数百 FPS 的推理速度。YOLO v8 的较大变体在 COCO 数据集上也已达到 50+ mAP,基本追平两阶段方法。
语义分割
语义分割的目标是对图像进行像素级的密集分类,为每个像素分配一个语义类别。
U-Net
U-Net 由 Ronneberger 等人于 2015 年提出,最初用于医学图像分割,因其卓越性能迅速成为语义分割的经典架构。
编码器-解码器结构(Encoder-Decoder):
- 编码器(下采样路径):由若干卷积层和池化层堆叠而成,逐步缩小空间分辨率、增加通道数,提取高维语义特征。典型的编码器包含 4-5 个下采样阶段。
- 解码器(上采样路径):使用转置卷积或上采样层逐步恢复空间分辨率,将编码器提取的语义特征映射回原始图像尺寸。
跳跃连接(Skip Connection) 是 U-Net 的核心创新:编码器每个阶段的特征图通过跳跃连接直接传递到解码器对应阶段,与上采样后的特征图进行拼接(concatenation)。跳跃连接的作用在于:
- 为解码器提供低层的空间细节信息(边缘、纹理等),弥补下采样过程中丢失的细粒度特征
- 帮助梯度更好传播,缓解深层网络中的梯度消失问题
- 使模型同时利用高低层信息,提升分割边界的精度
U-Net 因此成为医学图像分割的标配方法,其变体(如 U-Net++、Attention U-Net、nnU-Net)在各类医学分割竞赛中占据主导地位。
DeepLab 系列
DeepLab 系列由 Google 团队开发,核心创新在于利用空洞卷积(Dilated Convolution)在不降低特征图分辨率的前提下扩大感受野。
空洞卷积在标准卷积核的元素之间插入空洞(记为 dilation rate r),使得卷积核的覆盖范围从 k×k 变为感知范围更大的区域。例如,一个 3×3 卷积核在 dilation rate=2 时覆盖 5×5 的区域,且参数量不变。
ASPP(Atrous Spatial Pyramid Pooling) 是 DeepLabv3 的核心模块:并行的将输入特征图送入多个 dilation rate 不同的空洞卷积层(通常为 r=1, 6, 12, 18),再将输出拼接起来。ASPP 通过多尺度空洞卷积捕获不同尺度的上下文信息,大幅提升了模型在分割边界和细小结构上的表现。
DeepLabv3+ 在此基础上加入了解码器模块(使用 4 倍上采样的简单解码器),进一步提升分割结果的精细度。
实例分割
实例分割同时需要检测每个实例并生成其精确的像素级掩码,最具代表性的方法是 Mask R-CNN。
Mask R-CNN
Mask R-CNN 由 He 等人于 2017 年提出,在 Faster R-CNN 的基础上添加了一个并行的 Mask 分支,实现了实例分割任务。
架构设计:Mask R-CNN 采用"共享骨干 + 三个分支"的结构:
- 共享骨干:使用 ResNet + FPN(特征金字塔)提取多尺度特征
- RPN 分支:与 Faster R-CNN 一致的候选区域生成
- Fast R-CNN 分支:包含分类和边界框回归两个子分支
- Mask 分支:新增的并行分支,对每个 ROI 预测一个 K 个类别的二值掩码(每个类别一张掩码图),分辨率为 28x28
ROI Align 的作用:实例分割对位置精度要求极高,ROI Pooling 的量化误差会导致掩码边界错位。Mask R-CNN 使用 ROI Align 完全消除了量化操作,通过双线性插值实现亚像素精度的特征提取,这是 Mask R-CNN 能够实现高质量实例分割的关键技术。
训练损失:$L = L_{cls} + L_{box} + L_{mask}$
其中 Mask 分支对每个 ROI 输出 K×m×m 的掩码(K 为类别数),而 $L_{mask}$ 仅对 ROI 的真实类别对应的通道计算二值交叉熵损失,迫使各通道学习专注于各自类别的掩码预测。
Mask R-CNN 在 COCO 数据集上实现了当时最先进的实例分割和关键点检测结果,至今仍是实例分割的基准方法之一。
方法对比表
| 方法 | 任务 | 速度 | 精度 | 适用场景 |
|---|---|---|---|---|
| Faster R-CNN | 目标检测 | 中等(~10 FPS) | 高 | 精度优先的场景,如自动驾驶感知、工业缺陷检测 |
| YOLO(v8) | 目标检测 | 极快(>100 FPS) | 较高 | 实时性要求高的场景,如视频监控、移动端部署、边缘计算 |
| U-Net | 语义分割 | 中等 | 较高 | 医学图像分割、遥感图像分割、小样本分割 |
| Mask R-CNN | 实例分割 | 较慢(~5 FPS) | 高 | 需要实例级别分割的场景,如细胞分割、物体精细抓取 |
代码示例
以下使用 Ultralytics YOLOv8 进行目标检测推理的示例代码:
from ultralytics import YOLO
# 加载预训练模型(自动下载 COCO 权重)
model = YOLO("yolov8n.pt")
# 对图像进行推理
results = model("street_scene.jpg")
# 解析检测结果
for result in results:
boxes = result.boxes # 检测框
masks = result.masks # 分割掩码(如果有)
keypoints = result.keypoints # 关键点(如果有)
for box in boxes:
# 边界框坐标(xyxy 格式)
x1, y1, x2, y2 = box.xyxy[0].tolist()
# 置信度分数
conf = box.conf[0].item()
# 类别 ID
cls_id = int(box.cls[0].item())
# 类别名称
cls_name = result.names[cls_id]
print(f"{cls_name}: {conf:.2f} [{x1:.0f}, {y1:.0f}, {x2:.0f}, {y2:.0f}]")
# 保存带标注的图片
result_plot = results[0].plot()
import cv2
cv2.imwrite("street_scene_pred.jpg", result_plot)以上代码展示了 YOLOv8 最基础的用法:加载预训练模型、对图像进行推理、解析检测框结果并保存可视化结果。YOLOv8 的 API 设计简洁统一,同样的接口也可用于分割(YOLOv8n-seg.pt)、姿态估计(YOLOv8n-pose.pt)等任务。