想象你站在一个熙熙攘攘的露天集市入口,朋友说好在这里见面,但你不知道他蹲在哪个摊位前。你当然不会冲进人群挨个拍肩膀,而是先踮起脚尖环顾全场,锁定几个“可能是他”的身影,再逐一走近确认。这个“先粗扫一遍、再细看确认”的策略,就是两阶段目标检测(Two-Stage Object Detection)的核心思想。R-CNN系列正是把这一思路做到极致的祖师爷:先在整张图里快速圈出若干“可能藏有目标”的候选区域,再对每个候选区域做精细的分类和定位。从R-CNN到Fast R-CNN再到Faster R-CNN,三代演变就像猎人的装备升级:从笨重的望远镜、到聪明的全景侦察兵、再到自带雷达的智能猎手,每一步都在解决上一代的痛点。本文用这个“集市寻友”的比喻,把三代经典方法讲得明明白白。

岗位关联

掌握R-CNN系列两阶段检测的演进逻辑,是理解现代目标检测(Faster R-CNN、Mask R-CNN)的基石,也是算法工程师面试中几乎必考的知识点。

目录
  1. 可视化演示
  2. 两阶段思想:先粗后精的侦察术
  3. 候选区域生成:猎人的望远镜
  4. R-CNN原理:第一个认真的猎人
  5. R-CNN的不足:笨重装备的代价
  6. Fast R-CNN改进:聪明的共享侦察兵
  7. Faster R-CNN革命:自带雷达的猎手
  8. 演进总结:三代猎人的故事
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示R-CNN系列三代方法的检测流水线演进:从R-CNN的选择性搜索到Faster R-CNN的端到端RPN,两阶段检测精度持续提升。切换模式对比不同架构。

本节配有交互动效(进入视口后自动加载,约 3KB)。

R-CNN检测流水线 选择性搜索生成~2000个候选区域,每个独立送入CNN提取特征 SVM分类+边界框回归,速度极慢约0.05fps Speed ≈ 47s/image R-CNN开创了深度学习目标检测先河

两阶段思想:先粗后精的侦察术

集市入口人声鼎沸,你在人群边缘踮脚扫视,先锁定几个“像朋友”的背影,再穿过人群走近一一确认。这套策略之所以高效,是因为“粗扫”非常便宜——扫一眼全场只需要几秒钟,而“细认”很贵——挤过人群走近一个人需要好几分钟。两阶段目标检测正是这个逻辑的算法翻版:先用轻量方法快速圈出可能包含目标的候选区域,再用重型分类器仔细确认每块区域里到底是什么。

把这种直觉搬到计算机视觉里,目标检测的任务是回答两个问题:图像中有什么(分类),以及它在哪(定位)。两阶段方法把答案拆成两步流水线。第一步在整张图上生成几百上千个候选区域,不需要知道里面是什么,只要“这里可能有东西”就够了。第二步对每个候选区域提取特征、判断类别、修正边界框坐标。这样拆开后,正负样本可以分开处理,分类器面对的是经过筛选的、质量更高的输入,因此精度通常优于一步到位的单阶段方法。

代价也很直观:多了一个阶段,就多了一轮扫描和筛选的开销。单阶段方法看一眼全场就直接报结论,而两阶段方法无论如何都要先粗扫一遍、再逐个细看,速度自然慢。但正是这“多看一眼”的耐心,让两阶段方法在精度上长期领先,成为追求检测效果场景的首选。R-CNN系列正是把这一思想从笨拙推到优雅的完整标本。

Detection=Region Proposal⏟候选区域生成+Classification+Regression⏟分类与定位\text{Detection} = \underbrace{\text{Region Proposal}}_{\text{候选区域生成}} + \underbrace{\text{Classification} + \text{Regression}}_{\text{分类与定位}}

1. 候选区域生成:第一步从图像中找出若干可能包含目标的区域,输出一组候选框坐标。

Region Proposal={b1,b2,…,bn}\text{Region Proposal} = \{b_1, b_2, \ldots, b_n\}

2. 分类与定位:对每个候选框做类别判断,并回归修正其位置和尺寸。

Classification(bi)→(ci,scorei),Regression(bi)→Δ(x,y,w,h)\text{Classification}(b_i) \to (c_i, \text{score}_i), \quad \text{Regression}(b_i) \to \Delta(x, y, w, h)

集市上你扫视全场锁定几个身影,就是候选区域生成;走近一个个拍肩确认长相和位置,就是分类与定位。两阶段思想本质上是一种“先便宜后昂贵”的注意力分配策略:把最贵的算力花在最可能的地方。

候选区域生成:猎人的望远镜

找朋友最笨的办法是从集市入口开始,沿每个摊位逐寸搜索——这就是传统的滑动窗口法:用不同大小的窗口在整张图上平移,把所有可能位置都枚举一遍。可一张图上的窗口数量高达几十万个,大部分区域空无一物。聪明的猎人会先拿起望远镜快速扫一圈,只关注那些“有动静”的角落。Selective Search(选择性搜索)就是这架望远镜。

Selective Search的思路来自图像分割:先把图像切成很多细碎的小区域,然后计算相邻区域在颜色、纹理、形状上的相似度,把相似的小区域不断合并成更大的区域。合并的过程中,那些颜色纹理独特、边界完整的物体自然浮出水面,成为候选区域。它不需要学习,是纯手工设计的启发式方法,却比暴力滑窗高效得多——一张图只需生成约 2000 个候选框,就能覆盖绝大多数可能的目标。

候选区域的好坏直接决定了两阶段检测的上限。如果望远镜漏看了某个角落,后面的分类器再强也白搭。为了评估候选区域质量,人们常使用 IoU(交并比)指标:计算预测框与真实框的交叠面积占二者总面积的比重。IoU 越高,说明候选框与目标贴合得越好,这个指标也会贯穿 R-CNN 系列的训练和评测。

IoU(A,B)=∣A∩B∣∣A∪B∣\text{IoU}(A, B) = \frac{|A \cap B|}{|A \cup B|}

1. 交叠面积:计算两个框相交区域的面积,记为两个矩形重叠部分的宽乘高。

∣A∩B∣=woverlap×hoverlap|A \cap B| = w_{\text{overlap}} \times h_{\text{overlap}}

2. 并集面积:两个框各自面积之和减去交叠面积。

∣A∪B∣=∣A∣+∣B∣−∣A∩B∣|A \cup B| = |A| + |B| - |A \cap B|

3. 交并比:交叠面积与并集面积相除,结果落在 0 到 1 之间。

IoU=∣A∩B∣∣A∪B∣∈[0,1]\text{IoU} = \frac{|A \cap B|}{|A \cup B|} \in [0, 1]

望远镜扫到“可能像朋友”的身影后,你要判断这个身影是否真的和朋友的轮廓高度重合,IoU 就是这种“重合程度”的数学度量。集合里的相似度越高,越值得走近细看。

R-CNN原理:第一个认真的猎人

2014 年,R-CNN(Region-based CNN)横空出世,它第一次把深度学习引入目标检测,堪称“第一个认真的猎人”——拿着望远镜仔细扫描,每看到一个可疑身影就跑过去凑近观察。它的完整流程可以概括为“候选区域 + CNN 特征 + SVM 分类 + 回归修正”四步曲。

具体来说,先用 Selective Search 从图像中生成约 2000 个候选区域。这些区域尺寸各异,而 CNN 要求输入固定大小,因此 R-CNN 将每个候选区域裁剪出来,缩放到 227×227 像素,再送入卷积神经网络提取一个 4096 维的特征向量。特征向量随后被喂给两类头:一类是 SVM 分类器,判断这个区域属于哪个类别(猫、狗、鸟还是背景);另一类是边界框回归器,输出偏移量来修正候选框的位置,让框更贴合目标真实轮廓。

Prediction=SVM(CNN(Warp(Region)))\text{Prediction} = \text{SVM}\left(\text{CNN}\left(\text{Warp}(\text{Region})\right)\right)

1. 裁剪缩放 Warp:将候选区域从原图中裁剪出来,并统一缩放到 CNN 要求的固定尺寸。

Warp(Region)→R227×227×3\text{Warp}(\text{Region}) \to \mathbb{R}^{227 \times 227 \times 3}

2. CNN 特征提取:用预训练的卷积网络把图像块编码成一个固定长度的特征向量。

CNN(⋅)→R4096\text{CNN}(\cdot) \to \mathbb{R}^{4096}

3. SVM 分类:把特征向量送入支持向量机,输出每个类别的得分。

SVM(⋅)→{c1,c2,…,cK}\text{SVM}(\cdot) \to \{c_1, c_2, \ldots, c_K\}

猎人终于找到了一个“疑似朋友”的身影,他先走近把对方从头到脚打量一遍(Warp),在心里默默记下这个人的形态特征(CNN 特征),最后确认“是朋友”还是“认错了人”(SVM 分类)。如果确认是朋友,他还会顺便修正自己最初看错的位置偏差——这就是边界框回归。

R-CNN的不足:笨重装备的代价

这个猎人虽然认真,但装备实在是笨重。最致命的缺陷是速度:每张图像生成约 2000 个候选区域,每个候选区域都要单独缩放过一遍 CNN。即使候选区域之间有大量重叠,CNN 也会重复计算相同的卷积特征。这就好比猎人看到五个疑似身影,明明五个身影离得不远,他却偏要每个都跑回家拿一次望远镜再看——五次往返全是为了拿同一个望远镜。

Total Cost=Nregions×Cost(CNN Forward)\text{Total Cost} = N_{\text{regions}} \times \text{Cost}(\text{CNN Forward})

1. 候选区域数量:Selective Search 每张图生成约 2000 个候选区域。

Nregions≈2000N_{\text{regions}} \approx 2000

2. 单次前向成本:每个区域都要执行一次完整 CNN 前向传播,区域之间彼此独立。

Costtotal=∑i=12000Cost(CNN(i))\text{Cost}_{\text{total}} = \sum_{i=1}^{2000} \text{Cost}(\text{CNN}^{(i)})

除了速度慢,R-CNN 的训练流程也极其繁琐:要先用大量数据预训练 CNN,再在检测数据集上微调网络,接着还要为每个类别单独训练一个 SVM,最后再训练边界框回归器,四个阶段环环相扣,调参让人崩溃。同时,每个候选区域提取出的 4096 维特征都要存到磁盘上供 SVM 训练使用——一张图大约 2000 个区域,一个数据集几万张图,存储以「GB」为单位居高不下。推理一张图需要 40 秒以上,检测一次差不多够泡一碗泡面了。

猎人发现这套打法虽准但实在跑不动。2000 个候选区域中,很多都是同一个目标的多个偏移版本,把它们一个个当独立样本处理,既浪费算力又浪费存储。真正的改进方向不是换一个更快的望远镜,而是改变整个流程的重复结构——能不能只跑一次,就把所有区域都看完?

Fast R-CNN改进:聪明的共享侦察兵

聪明的猎人换了一种玩法:不再逐个跑去看,而是先爬上集市的高岗,对整个广场拍一张全景照片,然后再拿着这张照片,用放大镜对每个疑似身影慢慢端详。这样只需要爬一次岗、拍一张照,后面的所有细看都在这张共享的照片上进行——这就是 Fast R-CNN 的核心思想:整张图只过一次 CNN,得到一张共享特征图,所有候选区域的计算都在特征图上完成。

ROI Pooling:Rh×w×C→RH×W×C\text{ROI Pooling} : \mathbb{R}^{h \times w \times C} \to \mathbb{R}^{H \times W \times C}

1. 共享特征图:整张图像输入 CNN,只做一次前向得到全图特征图。

Feature Map=CNN(Image),Shape=(h,w,C)\text{Feature Map} = \text{CNN}(\text{Image}), \quad \text{Shape} = (h, w, C)

2. 区域映射:把原图坐标的候选框按步长缩放到特征图上的对应位置。

(x,y,w,h)image→(xs,ys,ws,hs)feature(x, y, w, h)_{\text{image}} \to \left(\frac{x}{s}, \frac{y}{s}, \frac{w}{s}, \frac{h}{s}\right)_{\text{feature}}

3. 固定尺寸池化:把区域内特征划分为 H×W 个小格,每个格子取最大值作为输出。

ROI Pooling(bi)→RH×W×C\text{ROI Pooling}(b_i) \to \mathbb{R}^{H \times W \times C}

Fast R-CNN 的另一大改进是引入多任务损失:把分类和边界框回归合并到同一个网络里联合训练,不再需要分别训练 SVM 和回归器。损失函数由两部分相加:分类的 softmax 交叉熵,以及回归的 smooth L1 损失。这样一个网络、一次反向传播,就把特征提取、分类、定位全都学好了。推理一张图只需约 0.3 秒,比 R-CNN 快了近百倍。

全景照片带来一次红利:R-CNN 需要 2000 次独立前向计算,Fast R-CNN 只需要一次前向加 2000 次轻量的 ROI 池化。猎人终于摆脱了反复折返的疲惫,站在高岗上俯瞰全场,效率暴增。但这位猎人还面临最后一个问题——拍照前,他仍然需要肉眼寻找哪些地方值得关注,这个“找位置”的动作仍然靠手动望远镜完成。

Faster R-CNN革命:自带雷达的猎手

Fast R-CNN 虽然快了,但候选区域仍由 Selective Search 在 CPU 上生成,这一步在整条链路中反而成为新的瓶颈。聪明的猎手干脆把望远镜扔掉,给自己的头盔装上智能雷达(RPN,Region Proposal Network)——雷达自动扫描全场,实时标出可疑目标,猎手只需要对雷达标出的位置进行确认。这就是 Faster R-CNN:让一个深度神经网络 RPN 来生成候选区域,并和检测网络共享卷积特征。

RPN 的核心机制是锚点(Anchor):在特征图上的每个位置预先放置一组不同尺度和长宽比的参考框(比如 3 种尺寸 × 3 种比例 = 9 个锚点),RPN 判断每个锚点内部是否包含物体,同时回归修正锚点框的坐标。锚点相当于雷达发射的探测波束,不同波束覆盖不同大小的目标,使得 RPN 能应对各种尺度的物体。

RPN 和检测网络共享特征图,训练时通过联合损失端到端优化:RPN 的候选质量影响检测网络,检测网络的梯度也会回流改善特征提取。至此,整个 R-CNN 系列终于进化成“一条龙”的端到端系统:输入图像、输出检测结果,中间的所有模块都参与联合训练。推理速度约 0.2 秒一张图,精度进一步提升。

L({pi},{ti})=1Ncls∑iLcls(pi,pi∗)+λ1Nreg∑ipi∗ Lreg(ti,ti∗)L(\{p_i\},\{t_i\}) = \frac{1}{N_{cls}}\sum_{i} L_{cls}(p_i, p_i^*) + \lambda \frac{1}{N_{reg}}\sum_{i} p_i^* \, L_{reg}(t_i, t_i^*)

1. 分类损失:判断每个锚点是否包含目标,用二分类交叉熵衡量预测与真实标签的差距。

Lcls(pi,pi∗)=−pi∗log⁡pi−(1−pi∗)log⁡(1−pi)L_{cls}(p_i, p_i^*) = -p_i^* \log p_i - (1 - p_i^*) \log(1 - p_i)

2. 回归损失:对包含目标的锚点,用 smooth L1 损失修正框的位置偏移量。

Lreg(ti,ti∗)=smoothL1(ti−ti∗)L_{reg}(t_i, t_i^*) = \text{smooth}_{L_1}(t_i - t_i^*)

3. 总损失:所有锚点的分类损失和回归损失分别求平均后,按权重 λ 相加。

L=Lcls+λLregL = L_{cls} + \lambda L_{reg}

雷达锁定可疑目标后,猎手只需确认目标类型即可,不再需要肉眼搜遍全场。RPN 让候选区域生成本身变成可学习的一部分,与特征提取共享——这就像雷达直接建立在猎手的视觉系统上,看到即感知,感知即锁定,整个寻人过程一气呵成。

演进总结:三代猎人的故事

从 R-CNN 到 Fast R-CNN 再到 Faster R-CNN,三代猎人的装备进化一目了然。R-CNN 是手持望远镜的笨拙猎人,跑动多、效率低但方向正确;Fast R-CNN 是爬上高岗拍照共享的聪明猎人,消除了 99% 的重复跑动;Faster R-CNN 则是配备智能雷达的顶尖猎人,从人工扫视升级为全自动感知。三代方法的共同点在于始终坚守“先粗后精”的两阶段思想,团队分工明确:先由轻量模块筛选候选,再由精细模块确认分类和位置。

| 方法 | 候选区域生成 | 共享特征 | 训练方式 | 速度(约) |

|------|-------------|---------|---------|-----------|

| R-CNN | Selective Search | 无 | 多级分步 | 40 秒/图 |

| Fast R-CNN | Selective Search | 有 | 多任务联合 | 0.3 秒/图 |

| Faster R-CNN | RPN(网络) | 有 | 端到端联合 | 0.2 秒/图 |

两阶段方法的精度优势来自“先筛选后精修”的结构化解耦:候选区域生成环节滤掉了大量背景,分类器面对的是经过预筛的样本,正负样本比例更均衡,分类边界更清晰。代价则是多一个阶段带来的额外计算,速度仍低于 YOLO 这类单阶段方法。因此业界形成了一条心照不宣的经验法则:追求精度选两阶段,追求实时选单阶段。

R-CNN→共享特征Fast R-CNN→RPN 端到端Faster R-CNN\text{R-CNN} \xrightarrow{\text{共享特征}} \text{Fast R-CNN} \xrightarrow{\text{RPN 端到端}} \text{Faster R-CNN}

1. 第一次跃迁:R-CNN 到 Fast R-CNN,核心是“共享卷积特征”,把逐区域计算变为全图一次计算。

Cost=O(N×C)→O(C+N)\text{Cost} = O(N \times C) \to O(C + N)

2. 第二次跃迁:Fast R-CNN 到 Faster R-CNN,核心是“RPN 取代手工候选”,让整条流水线全部用深度网络表达。

Selective Search→RPN(共享特征)\text{Selective Search} \to \text{RPN}(\text{共享特征})

在集市寻友这个生活场景中,两阶段方法像是经验丰富的保镖:先扫全场锁定可疑人员,再逐一盘问确认身份,虽然比莽撞的直线冲阵慢,但极少认错人。R-CNN 系列的三代演进则是一段装备升级史,每一步都精准解决了前一代的痛点,最终成为深度学习目标检测时代最经典的奠基之作。

AI 应用场景

自动驾驶中的车辆行人检测

阶段:目标检测(两阶段检测算法选型)

解决的问题:自动驾驶需要从车载摄像头图像中精准识别车辆、行人、骑行者等目标。传统机器学习方法在复杂天气与多变环境下误检率极高。两阶段检测的先粗后精策略能够先快速锁定可疑区域,再精细分类,大幅降低漏检、误检,尤其在行人这类小目标检测上精度优势明显。

具体案例:某自动驾驶公司的感知模块,使用 Faster R-CNN 作为核心检测器。摄像头采集图像后,RPN 在共享特征图上生成约 300 个候选区域,检测头对候选区域逐一分类和回归,输出目标的类别、置信度和精确边界框。相比单阶段检测器,在 KITTI 数据集上行人检测 mAP 高出 5 个百分点,误触发报警次数显著减少。

医学影像中的病灶检测

阶段:医学影像分析(候选区域 + 精细分类)

解决的问题:在 CT 或 X 光影像中,病灶往往只占画面极小比例,且与组织背景高度相似。单阶段检测器容易在密集背景中丢失小病灶。两阶段方法的候选区域生成环节先筛选出可疑区域,分类环节再深入判断是良性结节、恶性肿瘤还是伪影,从结构上保证了极高的召回率和判别的准确性。

具体案例:某三甲医院与 AI 公司合作的肺结节筛查系统,基于 Faster R-CNN 检测 CT 图像中的肺结节。RPN 通过多尺度锚点适应不同大小结节,检测头输出恶性概率和结节坐标。在真实临床数据集上,系统召回率达到 92%,帮助影像科医生将阅片时间从平均 15 分钟缩短到 3 分钟,且有效降低了微小结节的漏检。

遥感图像中的多尺度目标检测

阶段:遥感图像解译(两阶段精细检测)

解决的问题:遥感图像中不同地物(飞机、船舶、车辆)的尺寸跨度极大,且存在大量遮挡与旋转朝向差异。传统滑窗方法计算量爆炸且难以覆盖多种尺寸。两阶段方法依靠锚点机制天然支持多尺度检测,第一阶段快速筛选潜在目标,第二阶段精细回归任意朝向的边界框,适合高精度遥感解译任务。

具体案例:某遥感公司使用两阶段检测框架处理卫星图像,检测港口中的船舶与停机坪上的飞机。通过 RPN 的 9 种锚点组合覆盖宽比各异的舰船目标,再通过检测头的精确回归输出带旋转角度的边界框。在公开遥感数据集 DOTA 上,该方法平均检测精度达到 75% 以上,为地理信息分析提供了可靠的自动化工具。

Python 演示

python57 行
# -*- coding: utf-8 -*-"""模拟R-CNN两阶段目标检测的简洁演示"""import numpy as np  class SimpleRCNN:    """R-CNN两阶段检测: 候选区域 + 特征提取 + 分类"""     def __init__(self, num_regions=5, threshold=0.2):        self.num_regions = num_regions        self.threshold = threshold        self.results = []     def region_proposal(self, image):        """第一阶段: 生成候选区域(模拟Selective Search)"""        h, w = image.shape[:2]        regions = []        np.random.seed(42)        for _ in range(self.num_regions):            x = np.random.randint(0, max(1, w - 20))            y = np.random.randint(0, max(1, h - 20))            rw = np.random.randint(20, min(60, w))            rh = np.random.randint(20, min(60, h))            regions.append([x, y, rw, rh])        return regions     def feature_extract(self, image, region):        """提取区域特征: 模拟CNN输出颜色直方图特征"""        x, y, rw, rh = region        patch = image[y:y + rh, x:x + rw]        hist, _ = np.histogram(patch, bins=8, range=(0, 256))        return np.concatenate([hist, [np.mean(patch)]])     def classify(self, feature):        """第二阶段: 模拟SVM分类与置信度打分"""        score = np.mean(feature) / 255.0        return score > self.threshold, score     def detect(self, image):        """完整的两阶段检测流程"""        for region in self.region_proposal(image):            feat = self.feature_extract(image, region)            is_obj, score = self.classify(feat)            if is_obj:                self.results.append((region, float(score)))        return self.results  if __name__ == "__main__":    # 构造一张模拟图像: 100x100 中间有亮斑模拟目标    img = np.zeros((100, 100), dtype=np.uint8)    img[30:55, 40:65] = 200    detector = SimpleRCNN(num_regions=8)    detections = detector.detect(img)    print("检测到 {} 个目标区域:".format(len(detections)))    for region, score in detections:        print("  候选框: {}, 置信度: {:.3f}".format(region, score))
目的:用纯 NumPy 模拟 R-CNN 两阶段检测流程——先随机生成候选区域,再提取区域特征并分类,让读者直观理解“先候选、后分类”的两个阶段。
  1. self.results = []存放最终检测结果(候选框 + 置信度),作为检测器的输出缓存
  2. def region_proposal(self, image)第一阶段:生成候选区域,模拟 Selective Search 的输出
  3. np.random.randint(0, max(1, w - 20))随机生成候选框左上角坐标,确保坐标不越界
  4. def feature_extract(self, image, region)模拟 CNN 特征提取:裁剪区域并计算颜色直方图和均值
  5. np.histogram(patch, bins=8, range=(0, 256))对区域内的像素强度做 8 桶直方图统计,形成特征
  6. score = np.mean(feature) / 255.0模拟 SVM 打分:特征均值归一化到 0~1 作为置信度
  7. is_obj, score = self.classify(feat)第二阶段:对特征做分类判断并返回置信度
  8. img[30:55, 40:65] = 200在模拟图像中放置一个亮斑作为目标物体
  9. detector.detect(img)执行完整的两阶段检测流程并输出检测结果

常见误区

误区很多人以为 R-CNN 既然用了深度学习,候选区域应该也是卷积网络自动找的。其实 R-CNN 用的还是传统图像算法,深度网络只负责区域特征提取。

正解R-CNN 的第一阶段使用 Selective Search——一种基于图像分割和区域合并的纯算法,不涉及任何学习参数。CNN 只做第二阶段的工作:对候选区域提取特征,然后交给 SVM 分类。真正让候选区域由网络生成的是 Faster R-CNN 的 RPN。这个演进本质是从“传统算法找框”过渡到“神经网络找框”。

为何常见:容易把整套系统的能力归功于“深度学习”,忽略了早期模型对传统 CV 算法的依赖,也低估了 Faster R-CNN 把候选区域网络化这个跨越的意义。

误区初学者看到 R-CNN 一张图要 40 秒,第一反应是“网络太深、卷积计算量太大”,于是想去换一个更轻量的网络。

正解真正的瓶颈不在单次 CNN 前向,而在于 2000 个候选区域每个都要单独做一次 CNN 前向,而且这些区域高度重叠,卷积特征被重复计算了上千次。Fast R-CNN 用共享特征图一处改动就让速度提升近百倍,CNN 本身的复杂度几乎没变。这就像猎人跑 2000 趟去看同一个目标,问题不在看的速度,而在跑了太多次。

为何常见:人的直觉倾向于把性能瓶颈归结于“运算本身重”,而忽略“结构的重复浪费”,这正是理解 Fast R-CNN 改进的思维门槛。

误区有人画 R-CNN 结构图时,把整张图直接输进 CNN 然后输出检测框,误以为 R-CNN 是全卷积的端到端检测器。

正解R-CNN 的输入是已经被 Selective Search 框好的一个个候选区域裁剪块,每个裁剪块缩放到 227×227 后独立过 CNN。它本质上是“分类器级别的检测”——把检测拆成对候选框的分类问题,而不是用卷积回归直接预测目标位置。直到 Faster R-CNN,整张图的共享特征才成为真正端到端的输入。

为何常见:现代检测器(如 YOLO、Faster R-CNN)都是整图输入,画图时容易把今天的习惯套到 R-CNN 上,混淆了不同代际的输入输出结构。

误区有些初学者把两阶段方法精度高简单归结为“模型更大、参数更多”,试图通过加大单阶段网络来追平两阶段精度。

正解两阶段的精度优势更多来自结构上的先粗后精:候选区域生成环节滤除了绝大多数背景区域,使分类器面对的候选框正负样本比例更均衡,分类边界更清晰。单阶段方法直接在密集位置预测目标,正负样本极端不平衡,需要 Focal Loss 等特殊手段来缓解。结构差异大于参数量的差异。

为何常见:人们习惯用“容量”解释效果,而忽视“归纳偏置”和“样本分布”对模型精度的重要影响,这是理解检测算法演进的关键盲区。

面试题

Q1. 两阶段目标检测中“两阶段”是指哪两个阶段?

单选题 · easy

  • A.特征提取与目标分类
  • B.候选区域生成与分类回归← 正确答案
  • C.图像分割与目标检测
  • D.模型训练与推理部署

答案:B。两阶段检测的第一步是生成候选区域(“哪里可能有目标”),第二步是对候选区域进行分类和定位回归(“是什么、在哪”)。特征提取贯穿两阶段而非独立阶段;图像分割和目标检测是任务而非阶段;训练推理是所有模型都有的过程。就像集市寻友:先粗扫锁定身影,再走近确认身份。

Q2. R-CNN 中使用什么方法生成候选区域?

单选题 · easy

  • A.区域生成网络 RPN
  • B.锚点机制预测
  • C.选择性搜索 Selective Search← 正确答案
  • D.暴力滑窗遍历全图

答案:C。R-CNN(2014年)使用 Selective Search 这种传统图像分割合并算法生成候选区域,深度学习只负责后续特征提取和分类。RPN 是 Faster R-CNN 的贡献;锚点依附于 RPN 机制;暴力滑窗是传统方法的低效做法。类比:R-CNN 的猎人用的是手动望远镜,还没装上雷达。

Q3. Fast R-CNN 相比 R-CNN 最核心的改进是什么?

单选题 · mid

  • A.采用更深的卷积网络
  • B.整图共享卷积特征与 ROI 池化← 正确答案
  • C.使用更大规模的数据集
  • D.用单阶段替代两阶段结构

答案:B。Fast R-CNN 的杀手锏是让整张图只过一次 CNN,得到共享特征图,再用 ROI 池化把各候选区域映射为固定尺寸特征,消除了 R-CNN 中每个区域独立前向的重复计算。更深网络、更大数据集只是增量改进,单阶段替代两阶段是方向性的否定而非改进。

Q4. R-CNN 的缺点包括哪些?

多选题 · mid

  • A.重复计算导致推理极慢← 正确答案
  • B.训练分多级且复杂度高← 正确答案
  • C.需要存储大量中间特征← 正确答案
  • D.完全无法完成检测任务

答案:ABC。R-CNN 三个致命伤:2000 个候选区域各自过 CNN 导致重复计算(A)、CNN 微调+SVM+回归器多级训练流程繁琐(B)、每张图需要存储上万维特征到磁盘(C)。但它能完成检测任务,只是效率低,D 显然是错的。

Q5. ROI 池化的核心作用是什么?

单选题 · mid

  • A.将图像缩放至统一尺寸
  • B.将任意尺寸候选区域映射为固定尺寸特征← 正确答案
  • C.将彩色图像转换为灰度图像
  • D.对候选区域做非极大值抑制

答案:B。ROI 池化把大小不一的候选区域在共享特征图上切块,每块做最大池化,输出固定维度的特征向量,使后续全连接层能够处理不同尺寸的输入。图像缩放是 R-CNN 的做法,灰度化是预处理,NMS 是后处理,与 ROI 池化无关。

Q6. Faster R-CNN 用 RPN 替代 Selective Search 的最本质优势是什么?

单选题 · hard

  • A.RPN 生成候选框的速度提升了十倍
  • B.RPN 与检测网络共享特征并实现端到端联合训练← 正确答案
  • C.RPN 能生成比传统算法更多的候选框
  • D.RPN 不需要任何训练过程

答案:B。RPN 的最大价值不是单纯的“快”,而是候选区域生成模块本身变成了神经网络的一部分,与检测网络共享卷积特征,可微分、可训练,使整个系统实现端到端联合优化。速度提升只是表象,更深层的是“手工算法”到“学习网络”的本质转变。

Q7. 关于 RPN 中的锚点机制,下列说法正确的是?

多选题 · hard

  • A.锚点是预定义的多种尺度与长宽比的参考框← 正确答案
  • B.锚点是全连接层中的权重参数
  • C.锚点机制让网络适应不同大小的目标← 正确答案
  • D.锚点数量越多检测精度一定越高

答案:AC。锚点是特征图每个位置预先放置的一组不同尺度和长宽比的参考框,用于匹配不同大小的真实目标,因此 A 对、C 对。锚点不是网络参数而是先验设定;锚点数量过多会带来正负样本严重不平衡,精度不一定升高,B、D 错。

Q8. 两阶段方法比单阶段方法精度更高的主要原因是什么?

单选题 · easy

  • A.两阶段使用了更大的网络模型
  • B.先粗后精缓解了正负样本不平衡← 正确答案
  • C.两阶段不需要非极大值抑制
  • D.单阶段不使用卷积特征

答案:B。两阶段先靠候选区域筛选掉大量背景,使进入分类器的大多是“疑似目标”区域,正负样本比例更均衡。单阶段在密集位置直接预测,绝大多数预测框都是背景,训练难度更高。两阶段更需要 NMS,单阶段同样用卷积特征。

Q9. 以下哪个是 R-CNN 系列正确的演进顺序?

单选题 · mid

  • A.R-CNN → Faster R-CNN → Fast R-CNN
  • B.Fast R-CNN → R-CNN → Faster R-CNN
  • C.R-CNN → Fast R-CNN → Faster R-CNN← 正确答案
  • D.Faster R-CNN → Fast R-CNN → R-CNN

答案:C。历史顺序是 R-CNN(2014)→ Fast R-CNN(2015)→ Faster R-CNN(2016)。每个模型解决前一个的核心痛点:R-CNN 重复计算 → Fast 共享特征;Fast 的手工候选 → Faster 的 RPN 网络。类比为猎人装备升级:望远镜 → 全景照片 → 智能雷达。

Q10. 关于两阶段目标检测,以下描述正确的是?

多选题 · mid

  • A.精度通常高于单阶段方法← 正确答案
  • B.推理速度通常慢于单阶段方法← 正确答案
  • C.Faster R-CNN 的 RPN 无需训练
  • D.三个模型均以先粗后精为核心← 正确答案

答案:ABD。两阶段先粗选后精修的结构带来了精度优势但牺牲了速度,A、B 正确。Faster R-CNN 的 RPN 是需要联合训练的神经网络,C 错误。R-CNN、Fast R-CNN、Faster R-CNN 都遵循先候选后分类的两阶段思想,区别仅在候选区域如何生成,D 正确。