目标检测是计算机视觉领域的核心基础任务之一,许多刚入门这一方向的同学首先遇到的难题就是:主流的目标检测算法究竟是如何运作的?本文会先阐释目标检测需要解决的核心问题,再逐步梳理几个关键的检测框架——重点聚焦在 Faster R-CNN、SSD 和 YOLO 上。透彻理解这三个框架,基本就能掌握近年目标检测技术的发展主线。
(注:后续可能会陆续撰写一系列对象检测相关的论文阅读笔记,因此在正式研读论文之前,先把当前的研究现状、各类主流方法的基本原理串联一遍,这样后面读论文会更加顺畅。细节部分随后通过精读论文来补充。本文撰写时尚未逐一啃完所有原始文献,若理解有不到位之处,欢迎指正。首先放一张 RCNN 系列的示意图:)

Object Detection Tasks
目前计算机视觉(CV)与自然语言处理(NLP)、语音识别并列为深度学习领域的三大热点方向。而计算机视觉内部包含四个基本任务——图像分类、目标定位及检测、语义分割、实例分割。具体来说:
- 图像分类:判断一张图像中是否存在某种物体。
- 物体检测识别:实际上可拆分为两个子任务——目标检测(定位物体在图像中的位置)和目标识别(判断找到的物体具体属于哪一类别)。
- 语义分割:根据内容(物体类别)将图像划分成不同的区域。
- 实例分割:按单个目标个体进行分割,每个目标对应一个独立区域。


无论最终要完成什么任务,目标检测都是计算机视觉领域中最先需要掌握的基础能力。
Methods
传统的计算机视觉问题解决思路大致是:图像 → 预处理 → 人工特征提取 → 分类。大部分精力都花在如何设计更优的手工特征和分类算法上,也诞生了不少经典成果。但问题也很明显:人工设计的特征往往适用性有限,泛化能力较弱——针对某类问题效果好,换一个场景效果就明显下降。
当前主流的深度学习解决思路是端到端的:输入图像,直接输出任务结果。当然内部仍然有阶段划分——通常是图像 → 特征提取网络 → 分类/回归。特征提取网络即各种深度神经网络结构,这方面的研究非常多,例如各层的激活函数、损失函数、网络结构设计、特征可视化等。为了让提取的特征更鲁棒、更有效,研究者考虑了各种问题,比如尺度不变性(典型代表是特征金字塔网络 FPN,专门应对小目标检测)。整个网络实际上分为两部分:前 N 层负责特征提取,输入图像,输出特征图;后 K 层负责分类/回归,输入特征图,输出最终结果。本质上与传统人工特征提取并无太大区别,只是特征提取算法变成了神经网络。后一部分其实也可以替换——确实有不少框架的第二部分采用了其他机器学习算法,例如 SVM。
因此需要明确自己的定位:是要做算法研究(研究神经网络本身,使特征提取更强大、分类更精准、速度更快,从网络结构、损失函数、激活函数入手,需要扎实的数学理论),还是解决某个具体应用问题(利用已有的优秀神经网络,侧重于研究解决问题的框架,当然很多时候也需要对已有算法做一些微调)?前者更偏理论,后者往往以工程为基础。
面对实际任务,如果你的目标是解决问题而不是发明新算法,那么最好不要从头设计一个全新的网络结构,也不要试图从零复现现有网络。更高效的做法是:寻找公开的实现和预训练模型,然后进行微调。通常的做法是移除最后一个全连接层和对应的 softmax,换上对应你任务的全连接层和 softmax,然后固定住前面的层,仅训练你添加的部分。如果训练数据较多,可以多微调几层,甚至微调所有层。
Algorithms
目标检测的基本思路是同时解决定位(localization)和检测(detection)。这是一个多任务学习问题:网络有两个输出分支。一个分支做图像分类(全连接 + softmax 判断目标类别,与普通图像分类的区别在于这里还需要一个“背景”类);另一个分支做回归,输出四个数字标记包围盒的位置(例如中心点横纵坐标和包围盒的长宽)。这个回归分支的输出仅在分类分支判定不是“背景”时才使用。
Region Proposal
为什么要引入候选区域?既然目标出现在图像中的某个区域,最直接的方法就是滑动窗口——遍历图像的所有位置,用不同大小的窗口在整个图上滑一遍,产生所有可能的矩形区域,然后逐一排查。思路简单,但计算量极为庞大。
候选区域生成算法通常基于图像的颜色、纹理、面积、位置等信息,合并相似的像素,最终得到一系列候选矩形区域。例如 Selective Search 或 EdgeBoxes 这类算法,一般只需几秒的 CPU 时间,典型候选区域数目约为 2k。与滑动窗口将图像所有区域都扫描一遍相比,基于候选区域的方法高效得多。此外,这些候选区域生成算法的查准率一般,但查全率通常较高,不容易漏掉目标。
Selective Search
“Segmentation as selective search for object recognition”, ICCV 2011; “Selective search for object recognition”, International Journal of Computer Vision 2013.
这篇论文实际上包含两部分:一是 Selective Search 方法本身,用于寻找候选区域;二是对找到的区域做特征提取和分类。由于现在特征提取和分类都使用了深度学习,我们更多是借鉴它的候选区域寻找算法。
基本做法是先将图像划分成很多小区域。划分方式有很多种,例如:
- 等间距划分 grid cell——每个区域大小相同,但内部像素分布不均匀,随机性大,而且无法满足目标多尺度的要求(当然可以用不同尺度划分,那就是 Exhaustive Search,计算复杂度太大)。
- 使用边缘保持的超像素划分。
- 用 Selective Search(SS)方法找出最可能的候选区域。
这一步可看作是对图像的过分割。SS 方法高明之处在于:预先划分的区域各种大小都有(满足多尺度要求),而且对过分割的区域还有一个合并过程(区域的层次聚类),最后剩下的都是最可能的候选区域。这样在已经过滤了一遍的区域上做后续识别,候选区域数量大大减少,速度自然就提升了。

总体思路:假设图像有 n 个预分割的区域 R = {R1, R2, …, Rn}。计算每个区域与相邻区域的相似度,得到一个 n×n 的相似度矩阵(同一个区域之间以及不相邻区域之间的相似度设为 NaN)。从矩阵中找出最大相似度值对应的两个区域,将它们合并成一个新区域。此时区域总数变为 n-1。然后重复这个过程(只需计算新区域与相邻区域的相似度,其余不用重算),重复一次区域总数就减 1,直到所有区域合并成同一个区域(即过程进行 n-1 次,区域总数最终变成 1)。算法流程如下:

- Step0:生成区域集 R。具体参考论文《Efficient Graph-Based Image Segmentation》,基于图的图像分割,起点仍是图像分割。
- Step1:计算区域集 R 中每个相邻区域的相似度 S = {s1, s2, …}。
- Step2:找出相似度最高的两个区域,合并为新区域,添加到 R 中。
- Step3:从 S 中移除所有与 step2 中合并区域相关的子集。
- Step4:计算新区域与所有相邻区域的相似度。
- Step5:跳至 step2,直到 S 为空。
相似度计算考虑了四个方面:颜色、纹理、尺寸和空间交叠。
EdgeBoxes
“Edge Boxes: Locating Object Proposals from Edges”, ECCV 2014.
这篇文章不涉及“机器学习”,纯粹是图像处理的方法。它利用边缘信息(Edge),确定一个 box 内完全包含的轮廓个数以及与 box 边缘重叠的 edge 个数。如果一个 box 内完全包含的轮廓个数越多,目标就越有可能出现在这个 box 里。基于这个思想给每个 box 打分,然后根据得分高低确定 proposal 信息(由大小、长宽比、位置构成)。后续工作就在这些 proposal 内部运行检测算法。
R-CNN
“Rich feature hierarchies for accurate object detection and semantic segmentation”, CVPR 2014.
R-CNN 是卷积神经网络进入目标识别领域的里程碑。直接看图理解它的结构:
流程:原图 → Selective Search 得到约 2k 个 Proposal Regions → 对每个 region 做 warp(类似 resize 操作,统一到相同尺寸) → ConvNet 提取特征 → 分类(SVM) + 回归(bounding box regression)。这里的 warp 操作是为了把不同大小的 proposal 统一成相同尺寸,方便输入相同的 ConvNet。SVM 分类器是针对每个类别单独训练好的,是不同的分类器。
R-CNN 的思路非常直接:对于输入图像,先用 Selective Search 确定例如 2000 个最有可能包含物体的窗口(要求召回率很高),然后对每个窗口单独用 CNN 做特征提取和分类。2000 个窗口每个都要跑一次 CNN,速度非常慢——即使每次只要 0.5 秒,2000 个窗口就是 1000 秒。为了加速,2014 年何恺明提出了 SPP-net:对整个图只跑一次 CNN,而不需要每个窗口单独做。但问题是 2000 个候选窗口大小不同,如何解决?SPP-net 设计了空间金字塔池化(Spatial Pyramid Pooling),使得不同大小的窗口能输出相同维度的特征。这个方法不再需要对每个候选窗口单独计算卷积,但一张图仍然需要几秒时间。
R-CNN 的不足:
- 多个候选区域对应的图像需要预先提取,占用大量磁盘空间。
- 传统 CNN 要求固定尺寸输入,crop/warp 会产生物体截断或拉伸,导致信息丢失。
- 每个 Proposal Region 都要进入 CNN 计算,上千个 Region 有大量重叠,重复特征提取造成巨大浪费。
SPP-Net
“Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition”, ECCV 2014, Kaiming He.
各个 Proposal Region 大小不一,全图只卷积一次的话,不需要经过 warp,但在特征图上寻找这些 Region 时仍然存在大小不一的问题。由于后面全连接层的输入维度必须统一,因此使用了 SPP(空间金字塔池化),不同尺寸的 Region 经过不同金字塔池化层,得到统一维度的输出。这样既加速了算法,又兼顾了尺度问题。
在 R-CNN 中,要求输入固定大小图片,需要 crop/warp,改变尺寸引起形变影响效果;而且每个 proposal 都要单独做 CNN 前向特征提取,2000 个 proposal 就是 2000 次前向,浪费大量时间。
SPP-Net 的改进:输入整张图像,提取整张图像的特征图,然后利用空间关系从特征图中,通过 SPP layer 提取每个 region proposal 的特征。

- 取消了 crop/warp 归一化,解决了图像变形导致的信息丢失和存储问题。
- 用空间金字塔池化替换了全连接层之前的最后一个池化层。
SPP 的两个主要特点:
1. 结合空间金字塔方法实现 CNN 的多尺度输入。一般 CNN 后面接全连接层或分类器,需要固定输入尺寸,因此不得不对输入做 crop/warp,这会造成数据丢失或几何失真。SPP Net 将金字塔思想加入 CNN,允许任意尺寸输入。在 SPP layer 中,每个 pooling 的 filter 会根据输入调整大小,而 SPP 的输出尺度始终固定。

2. 只对原图提取一次卷积特征。在 R-CNN 中每个候选框先 resize 到统一大小再分别作为 CNN 输入,效率很低。SPP Net 只对原图做一次卷积得到整张图的 feature map,然后找到每个候选框在 feature map 上的映射 patch,把这个 patch 作为候选框的卷积特征输入到 SPP layer 和后面的层。这比 R-CNN 快了大约一百倍。
SPP-Net 的不足:
- 和 R-CNN 一样,训练过程仍然是隔离的:提取候选框、计算 CNN 特征、SVM 分类、Bounding Box 回归独立训练,大量中间结果需要转存,无法整体训练参数。
- SPP-Net 无法同时调整 SPP layer 两边的卷积层和全连接层,限制了深度 CNN 的效果。
- Proposal Region 的生成仍然很耗时。
Fast R-CNN
“Fast r-cnn”, ICCV 2015, Girshick, Ross.
Fast R-CNN 是在 R-CNN 基础上吸收了 SPP Net 的思想,进一步改进性能。它在全图上做卷积,然后用 ROI-pooling 得到定长的特征向量——不管窗口大小是多少,都转换成 7×7 这样固定的大小。同时引入一个重要策略:在对窗口分类的同时,还对物体的边框做回归,让检测框更准确。前面提到候选窗口有很高的召回率,但位置可能不太准(比如人体框缺胳膊缺腿),回归可以对检测框做精调。Fast R-CNN 把分类和回归放在一起,采用多任务协同学习的方式。
ROI Pooling(兴趣区域汇合)的作用是:从任意大小的候选区域对应的局部卷积特征中提取出固定大小的特征——因为下一步两个分支网络里有全连接层,需要输入大小固定。做法是:先把候选区域投影到卷积特征上,再把对应的卷积特征区域空间上划分成固定数目的网格(网格数目根据下一步网络希望的输入大小确定,比如 VGGNet 需要 7×7 的网格),然后在每个小网格区域内做最大汇合,得到固定大小的结果。每个通道的兴趣区域汇合是独立的。

Faster R-CNN
“Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks”, NIPS 2015.

之前的 Fast R-CNN 已经基本实现端到端检测,但主要速度瓶颈在 Selective Search 算法实现的 Region Proposal 上。Faster R-CNN 要解决的就是 Region Proposal 问题,实现实时检测。核心思路:既然检测工作是在卷积结果 Feature Map 上做的,那候选区域的选取能不能也在 Feature Map 上做?于是 RPN(Region Proposal Network)应运而生。
候选框提取不一定要在原图上做,特征图上同样可以。低分辨率特征图意味着更少的计算量。基于这个假设,任少卿等人提出了 RPN,整体架构如上图所示。通过添加额外的 RPN 分支网络,将候选框提取合并到深度网络中——这正是 Faster R-CNN 里程碑式的贡献。
RPN 引入了 anchor box 的设计:在最后一个卷积层输出的特征图上,先用 3×3 的卷积得到每个位置的特征向量,然后基于这个特征向量去回归 9 个不同大小和长宽比的窗口。如果特征图大小是 40×60,那么总共就有大约 2 万多个窗口。把这些窗口按信度排序,取前 300 个作为候选窗口,送去做最终分类。
Faster R-CNN 实现了端到端的检测,几乎达到了效果上的最优,但小物体的识别仍然存在问题——SSD 算法就是针对这个问题诞生的。速度方面也还有改进空间,于是 YOLO 出现了。
SSD
SSD 算法是一种直接预测目标类别和 bounding box 的多目标检测算法。与 Faster R-CNN 相比,它没有生成 proposal 的过程,这极大提高了检测速度。针对不同大小的目标检测,传统做法是先把图像转换成不同尺寸(图像金字塔),分别检测,最后综合结果(NMS)。SSD 则利用不同卷积层的 feature map 进行综合,也能达到同样的效果。算法的主网络结构是 VGG16,把最后两个全连接层改成卷积层,并随后增加 4 个卷积层。对其中 5 种不同卷积层的输出(feature map)分别用两个不同的 3×3 卷积核进行卷积:一个输出分类用的 confidence(每个 default box 生成 21 个类别 confidence),一个输出回归用的 localization(每个 default box 生成 4 个坐标值 x, y, w, h)。此外,这 5 个 feature map 还经过 PriorBox 层生成 prior box(生成的是坐标)。每一层的 default box 数量是给定的(共 8732 个)。最后将前面三个计算结果分别合并然后传给 loss 层。
YOLO
2015 年出现的 YOLO 方法(最终发表在 CVPR 2016)思路比较独特:对于给定的输入图像,不管三七二十一都划分成 7×7 的网格,也就是得到 49 个窗口,然后在每个窗口中去预测两个矩形框。这个预测通过全连接层完成。YOLO 会预测每个矩形框的 4 个参数和它包含物体的信度,以及它属于每个物体类别的概率。速度非常快,在 GPU 上可以达到 45fps。
YOLO 的处理步骤:把输入图片缩放成 448×448;运行卷积网络;对模型置信度卡阈值,得到目标位置与类别。对 VOC 数据集,就是把图片统一缩放到 448×448,每张图平均划分为 7×7=49 个小格子,每个格子预测 2 个矩形框及其置信度,以及 20 种类别的概率。舍弃了 Region Proposal 阶段,速度很快,但定位精度比较低,分类精度也不高。在各类数据集上的平均表现大约为 54.5% mAP。
总结一下 RCNN 系列算法的步骤
RCNN
- 在图像中确定约 1000-2000 个候选框(使用选择性搜索)。
- 每个候选框内图像块缩放至相同大小,输入 CNN 进行特征提取。
- 对候选框中提取出的特征,用分类器判别是否属于特定类。
- 对于属于某一特征的候选框,用回归器进一步调整其位置。
Fast RCNN
- 在图像中确定约 1000-2000 个候选框(使用选择性搜索)。
- 对整张图片输进 CNN,得到 feature map。
- 找到每个候选框在 feature map 上的映射 patch,作为候选框的卷积特征输入到 SPP layer 和之后的层。
- 对候选框中提取出的特征,用分类器判别是否属于特定类。
- 对于属于某一特征的候选框,用回归器进一步调整其位置。
Faster RCNN
- 对整张图片输进 CNN,得到 feature map。
- 卷积特征输入到 RPN,得到候选框的特征信息。
- 对候选框中提取出的特征,用分类器判别是否属于特定类。
- 对于属于某一特征的候选框,用回归器进一步调整其位置。
三者比较
| 方法 | 创新 | 缺点 | 改进 |
|---|---|---|---|
| R-CNN | 1. SS 提取 RP;2. CNN 提取特征;3. SVM 分类;4. BB 盒回归。 | 1. 训练步骤繁琐(微调网络+训练 SVM+训练 bbox);2. 训练、测试均慢;3. 训练占空间。 | 1. 从 DPM HSC 的 34.3% 直接提升到了 66% (mAP);2. 引入 RP+CNN。 |
| Fast R-CNN | 1. SS 提取 RP;2. CNN 提取特征;3. softmax 分类;4. 多任务损失函数边框回归。 | 1. 依旧用 SS 提取 RP(耗时 2-3s,特征提取耗时 0.32s);2. 无法满足实时应用,未真正实现端到端训练测试;3. 利用了 GPU,但区域建议方法在 CPU 上实现。 | 1. 由 66.9% 提升到 70%;2. 每张图像耗时约 3s。 |
| Faster R-CNN | 1. RPN 提取 RP;2. CNN 提取特征;3. softmax 分类;4. 多任务损失函数边框回归。 | 1. 仍无法达到实时检测;2. 获取 region proposal 后再对每个 proposal 分类,计算量还是较大。 | 1. 提高了检测精度和速度;2. 真正实现端到端的目标检测框架;3. 生成建议框仅需约 10ms。 |
