查看全课大纲(第 61 / 93 节)
- 1.计算机视觉概述
- 2.计算机视觉应用场景
- 3.困难与挑战
- 4.开源库介绍
- 5.图像显示与存储
- 6.CLAHE
- 7.腐蚀膨胀与开闭运算
- 8.滤波与边缘填充
- 9.各种滤波
- 10.图像金字塔
- 11.傅里叶变换
- 12.短时傅里叶变换与小波变换
- 13.颜色特征与颜色直方图
- 14.几何特征_边缘
- 15.几何特征-角点与斑点
- 16.局部特征-SIFT特征描述子
- 17.局部特征-SURF特征描述子
- 18.局部特征-ORB特征描述子
- 19.其他特征描述子
- 20.传统图像分割技术
- 21.GraphCut
- 22.GrabCut
- 23.人脸检测的传统方法
- 24.行人检测的传统方法HOG+SVM
- 25.行人检测DPM
- 26.人工神经网络的架构
- 27.目标函数与梯度下降
- 28.误差反向传播
- 29.可手算的神经网络
- 30.改进目标函数与克服梯度消散
- 31.神经网络之传统神经网络与深度网络的差异
- 32.各种梯度下降算法
- 33.如何选择合适的梯度下降算法
- 34.避免过适应
- 35.CNN的架构
- 36.CNN的误差反向传播_卷积层
- 37.CNN的误差反向传播_池化层
- 38.分类所用的数据集
- 39.Alexnet详解
- 40.VGG详解
- 41.GoogLeNet_v1
- 42.BatchNormalization
- 43.GoogLeNet_v3v4
- 44.ResNet
- 45.ResNeXt
- 46.CNN设计准则
- 47.图像检索与推土机距离
- 48.基于颜色相似性
- 49.基于形状相似性
- 50.基于纹理相似性
- 51.基于局部特征相似性
- 52.DL的二值哈希编码
- 53.高维空间中检索KDTree
- 54.高维空间中检索LSH
- 55.目标识别任务综述
- 56.RCNN
- 57.SPP-Net
- 58.Fast R-CNN
- 59.Faster R-CNN
- 60.R-CNN系列模型回顾
- 61.R-FCN的设计思路
- 62.R-FCN的实现
- 63.YOLOv1
- 64.YOLOv2_9000
- 65.YOLOv3
- 66.图像分割应用场景与数据集
- 67.上采样的实现方式
- 68.FCN网络架构的由来
- 69.FCN构建细节
- 70.DeepLabv1
- 71.CRF
- 72.DeepLabv2
- 73.DeepLabv3
- 74.特定的医学影像分割任务
- 75.U-Net
- 76.3D U-Net
- 77.V-Net
- 78.DenseNet
- 79.病理切片分析任务及数据集
- 80.病理切片分析
- 81.图说任务及其传统处理方法
- 82.深度语言模型与RNN
- 83.LSTM及其变种
- 84.NIC模型
- 85.SAT模型
- 86.图说的性能指标
- 87.判别模型与生成模型
- 88.KL散度与JS散度
- 89.VAE
- 90.GAN的基本原理
- 91.DCGAN与CGAN
- 92.Wasserstein GAN
- 93.SRGAN
R-FCN的设计思路
小象实战讲义 · 基于深度学习的计算机视觉
在目标检测领域,随着基础网络从AlexNet、VGG向ResNet、GoogLeNet等全卷积化网络演进,直接将Faster R-CNN等经典框架嫁接于新网络之上遇到了性能瓶颈。本节将深入剖析这一矛盾的核心——检测任务的位置敏感性与分类任务的位置不变性之间的冲突,并引出R-FCN(Region-based Fully Convolutional Networks)如何通过“全卷积化”设计,在保持高精度的同时大幅提升检测速度。
💡 核心导读
- 传统R-CNN结构的局限性:基于AlexNet/VGG的“全卷积子网络+全连接子网络”结构,在适配ResNet等全卷积网络时,RoI-wise子网络的计算无法共享,成为速度瓶颈。
- 检测与分类的根本矛盾:检测网络需要位置敏感性以精确定位,而分类网络需要位置不变性以保证识别鲁棒性。深度全卷积网络(如ResNet)的深层特征具有强不变性,不利于定位。
- R-FCN的核心创新:通过引入位置敏感分值图和位置敏感RoI池化,将位置信息显式编码到全卷积网络中,实现了整个检测网络(包括分类与回归分支)的完全卷积化,所有计算均可共享,从而在精度与速度间取得优异平衡。
从经典结构到全卷积网络的适配困境
在Faster R-CNN及其前身中,网络结构通常基于如AlexNet或VGG这类“老式”CNN设计。这类网络具有清晰的模块划分:
- 全卷积子网络:通常指网络前部的若干组卷积层(如VGG的conv1-conv5)。这部分计算是独立于RoI(Region of Interest) 的,即整张输入图像只需经过一次前向传播,特征提取的计算可以被图像中所有候选区域共享。
- 全连接子网络:位于网络后部,用于最终的分类与边界框回归。在目标检测框架中,RoI池化层通常被插入在全卷积子网络与全连接子网络之间。这样,每个由RPN(Region Proposal Network)生成的候选区域(RoI)会被映射到特征图上,并经过RoI池化调整为固定尺寸,然后各自独立地通过后续的全连接子网络进行分类和回归。这部分计算是RoI-wise的,无法共享。
这种“前半共享,后半独立”的结构,在基础网络本身也具备类似划分(如VGG的conv部分和fc部分)时,显得非常自然。
然而,随着ResNet、GoogLeNet等现代网络架构的出现,情况发生了变化。为了减少参数、缓解过拟合并提升性能,这些网络极大地减少了全连接层的使用。以ResNet-101为例,它包含100个卷积层,最后仅接一个全局平均池化层和一个用于ImageNet 1000类分类的全连接层。网络的“全卷积化”成为趋势。
当试图将Faster R-CNN的头部(两个分支的全连接网络)直接嫁接在ResNet-101的末端(即去掉最后的全连接层)时,研究者发现检测性能出现了明显的下降。其根本原因在于任务属性的冲突:
- 分类任务需要位置不变性:理想的分类器应该能够识别出物体,无论它出现在图像的哪个位置。深度卷积网络通过层层池化和非线性变换,其深层特征确实具备了较强的平移不变性。例如,一张猫的图片,无论猫在左上角还是右下角,ResNet-101的深层特征都应能将其识别为“猫”。
- 检测任务需要位置敏感性:检测不仅要识别物体,还要给出其精确的边界框位置。因此,检测网络需要对物体的位置移动保持敏感。如果特征过于“不变”,网络将难以区分物体在图像中的细微位置变化,从而导致定位不准。
直接将RoI池化层放在ResNet-101的末端,意味着每个RoI都使用具有强不变性的深层特征进行分类和回归。这虽然对分类有利,但却严重损害了定位精度,造成了检测性能与分类性能的不匹配。
一种“不自然”的折中方案及其缺陷
为了解决上述矛盾,一个直观的改进思路是:将RoI池化层提前。例如,对于ResNet-101,将前91层卷积作为共享的卷积子网络,在第91层后插入RoI池化层,再用conv5_x剩余的9层主路卷积作为RoI-wise的子网络(另有1个投影捷径,故这一段的卷积算子共10个,但主路仍按9层计,91 + 9 = 100层)。
import numpy as np
# 模拟ResNet-101的特征图尺度变化(仅示意)
# 假设输入图像尺寸为 800x600
input_h, input_w = 600, 800
# ResNet-101通常包含5个stage,下采样率为32
# 最终特征图尺寸约为 input_size / 32
feat_map_h, feat_map_w = input_h // 32, input_w // 32
print(f"输入图像尺寸: {input_h}x{input_w}")
print(f"网络末端(第100层卷积)输出特征图尺寸: {feat_map_h}x{feat_map_w}")
# 假设第91层位于第4个stage末尾,下采样率为16
feat_map_h_91, feat_map_w_91 = input_h // 16, input_w // 16
print(f"第91层卷积输出特征图尺寸: {feat_map_h_91}x{feat_map_w_91}")
print(f"特征图尺度对比: 第91层({feat_map_h_91}x{feat_map_w_91}) 比 网络末端({feat_map_h}x{feat_map_w}) 更大")输入图像尺寸: 600x800
网络末端(第100层卷积)输出特征图尺寸: 18x25
第91层卷积输出特征图尺寸: 37x50
特征图尺度对比: 第91层(37x50) 比 网络末端(18x25) 更大这种设计将RoI池化置于一个空间分辨率更高的特征图上(例如37x50而非18x25),理论上有利于保留更多的位置信息,从而提升定位精度。实验也证实,这种“不自然”的设计确实带来了准确率的提升。
然而,它引入了新的问题:速度下降。因为RoI池化层之后的这10个卷积(conv5_x的9层主路卷积加1个投影捷径),仍然是RoI-wise的。假设一张图像产生300个候选区域,那么这300个区域的特征图都需要独立地经过这10层卷积计算。这相当于进行了300次小型卷积网络的前向传播,计算开销巨大,严重拖慢了检测速度。
R-FCN:全卷积化的解决方案
R-FCN的核心目标非常明确:实现目标检测网络的完全卷积化,使得所有计算(包括分类和回归)都能在整张图像上共享,彻底消除RoI-wise的子网络。
其创新点主要在于两个关键设计:
1. 位置敏感分值图
R-FCN在共享的卷积主干网络(如ResNet-101)之后,添加了一个特殊的卷积层,用于生成位置敏感分值图。假设我们要检测的类别数为C(加上背景类为C+1),并且我们将每个RoI划分成一个k x k的规则网格(论文示意图以k=3为例,正式实验配置为k=7)。
对于每一个类别c,我们不是只生成一个分值图,而是生成k x k个分值图。每个分值图专门负责预测该类别物体出现在RoI内某个特定相对位置的概率。例如,k=3时,这9个位置分别是:左上、中上、右上、左中、中心、右中、左下、中下、右下。
因此,这个特殊卷积层的输出通道数为 k * k * (C + 1)。对于输入图像,我们只需经过一次前向传播,就能得到所有类别、所有相对位置的分值图。
2. 位置敏感RoI池化
在得到位置敏感分值图后,对于每一个候选区域RoI,我们进行一种特殊的池化操作——位置敏感RoI池化。
- 将当前RoI区域同样划分为
k x k个网格(bin)。 - 对于第
(i, j)个网格(i, j从0到k-1),它只从对应类别c的第(i*k + j)个分值图中进行池化(通常是平均池化)。 - 池化后,我们得到一个
k x k的网格,每个格子包含了物体某部分出现在对应相对位置的“证据”。 - 最后,将这
k x k个格子的值进行求和,即得到该RoI属于类别c的最终得分(论文的公式用求和;课件与下面的演示代码则取平均,两者只差常数因子1/k²,各类别得分的相对大小与argmax预测类别不变)。
这个过程显式地将位置信息编码到了分类决策中。如果一个RoI确实包含目标物体,并且定位准确,那么其各个部分(如人的头、躯干、四肢)就应该落在RoI内正确的相对位置上,从而从对应的分值图中获得高分。反之,如果定位不准或根本不是目标,那么各个网格池化得到的分数就会很低或相互矛盾,最终得分也低。
import numpy as np
# 模拟R-FCN的位置敏感分值图与池化过程
np.random.seed(42) # 固定随机种子,保证输出确定
# 假设特征图尺寸为 40x60,类别数为20(人、车、狗...),k=3
H, W, C, k = 40, 60, 20, 3
# 生成位置敏感分值图 (H, W, k*k*(C+1)),这里用随机数模拟卷积输出
# 我们只关注‘人’这个类别(假设类别索引0为人)
score_maps_all = np.random.randn(H, W, k*k*(C+1))
# 提取‘人’类对应的 k*k=9 个通道的分值图
person_score_maps = score_maps_all[:, :, 0:9] # 假设前9个通道对应‘人’类
print(f"位置敏感分值图(‘人’类)形状: {person_score_maps.shape}")
print(f"每个图对应RoI内一个相对位置: 共 {k}x{k}={k*k} 个图\n")
# 假设有一个RoI,其坐标 (x1, y1, x2, y2) 映射到特征图上的区域为 (ry, rx, rh, rw)
# 简化为一个具体的区域:从(10,15)开始,高20,宽25
ry, rx, rh, rw = 10, 15, 20, 25
roi_feat = person_score_maps[ry:ry+rh, rx:rx+rw, :]
# 位置敏感RoI池化:将roi_feat划分为3x3网格,在每个通道对应的网格内做平均池化
pooled = np.zeros((k, k))
# 为简化,这里按整数除法分箱,边缘余数未纳入;真实实现会用浮点边界覆盖整个 RoI
bin_h, bin_w = rh // k, rw // k
for i in range(k):
for j in range(k):
# 第 (i,j) 个网格
h_start = ry + i * bin_h
h_end = min(ry + (i+1) * bin_h, ry+rh)
w_start = rx + j * bin_w
w_end = min(rx + (j+1) * bin_w, rx+rw)
# 对应第 (i*k + j) 个通道图
channel_idx = i * k + j
bin_values = person_score_maps[h_start:h_end, w_start:w_end, channel_idx]
pooled[i, j] = np.mean(bin_values)
print("RoI池化后得到的 3x3 网格值:")
print(pooled)
print()
# 最终得分:对3x3网格值求平均
final_score = np.mean(pooled)
print(f"‘人’类在该RoI上的最终得分(投票后): {final_score:.4f}")位置敏感分值图(‘人’类)形状: (40, 60, 9)
每个图对应RoI内一个相对位置: 共 3x3=9 个图
RoI池化后得到的 3x3 网格值:
[[-0.09602184 0.03350679 -0.14356285]
[ 0.03835107 -0.33898509 -0.07624601]
[-0.05805505 0.13031784 -0.46478488]]
‘人’类在该RoI上的最终得分(投票后): -0.1084边界框回归分支采用完全相同的设计,只是其输出的通道数变为 4 * k * k(对应4个坐标偏移量),并通过相同的位置敏感RoI池化得到回归结果。
通过这种巧妙的设计,R-FCN成功地将整个检测网络变成了一个全卷积网络。图像只需经过一次前向传播,就能生成所有必需的分值图。后续对于成百上千个RoI的处理,都仅仅是简单的、无参数的池化操作和求平均,计算量极低。从而在保持与Faster R-CNN相当甚至更优精度的同时,获得了显著的检测速度提升(论文报告约为 2.5–20 倍,具体取决于主干网络与实现配置)。
# R-FCN 网络结构示意 (伪代码)
输入图像 I
1. 共享卷积主干 (如ResNet-101) -> 特征图 F
2. RPN网络 (在F上运行) -> 候选区域提案 RoIs
3. 位置敏感卷积层 (接在主干后):
- 输入: 特征图 F
- 输出:
* 分类分支: 分值图 P_cls, 形状为 [H, W, k*k*(C+1)]
* 回归分支: 分值图 P_reg, 形状为 [H, W, 4*k*k]
4. 对于每个RoI:
a. 位置敏感RoI池化 (在P_cls上) -> 得到 k x k 网格分类得分
b. 在k x k维度上求平均 -> 得到 (C+1) 维分类得分向量
c. 位置敏感RoI池化 (在P_reg上) -> 得到 k x k x 4 回归偏移量
d. 在k x k维度上求平均 -> 得到 4 维边界框回归向量
5. 非极大值抑制 (NMS) -> 输出最终检测框📝 动手练一练
- 概念辨析:请用自己的话解释,为什么在深度全卷积网络(如ResNet)中,分类任务所追求的“位置不变性”与检测任务所要求的“位置敏感性”会构成一对矛盾?这种矛盾在Faster R-CNN直接嫁接ResNet时,是如何具体影响性能的?
👉 点击查看参考答案
矛盾根源:分类任务的目标是识别“是什么”,希望网络能够忽略物体在图像中的位置变化,聚焦于其本质特征(如纹理、形状),这要求特征具有平移不变性。检测任务的目标是“在哪里”和“是什么”,精确定位要求网络能够感知物体位置的细微变化,这要求特征具有平移敏感性(或方差)。深度卷积网络通过堆叠卷积和池化层,深层特征会逐渐丢失细节位置信息,变得对平移不敏感,这与检测任务的定位需求相悖。
性能影响:当Faster R-CNN将RoI池化层直接放在ResNet末端时,每个RoI使用的是具有强不变性的深层特征。这使得:
- 分类分支:可能表现良好,因为深层特征不变性强,有利于识别。
- 回归分支:表现变差,因为用于回归的深层特征对位置变化不敏感,网络难以学习精确的边界框偏移量。 最终导致整体检测性能(尤其是定位精度mAP)下降,出现分类性能与检测性能不匹配的现象。
- 思路理解:R-FCN通过“位置敏感分值图”和“位置敏感RoI池化”来解决上述矛盾。请简述这一方案是如何在不引入RoI-wise子网络的前提下,让网络同时具备分类能力(基于整体判断)和位置感知能力(基于局部网格)的?
👉 点击查看参考答案
R-FCN的方案可以概括为“分而治之,投票决策”:
- 分而治之(位置编码):网络不再为整个RoI输出一个单一的类别得分,而是为每个类别生成
k x k个分值图,每个图专门负责预测物体某一部分(对应RoI内一个特定相对位置)出现的可能性。这相当于将物体的位置信息显式地编码到了网络输出中。 - 投票决策(池化与聚合):对于每个RoI,进行位置敏感池化。将RoI划分为
k x k网格,每个网格只从对应位置的分值图中提取特征值。这样,如果RoI定位准确且包含目标,其各个部分就会从正确的分值图中获得高分;如果定位不准或没有目标,各网格得分会很低或混乱。最后,对k x k个网格的得分进行平均(投票),得到该RoI的最终类别得分。高分意味着RoI内物体的各个部分都出现在了“正确”的相对位置上,这同时蕴含了“它是某类物体”(分类)和“它被框得很准”(定位)两层信息。 通过这种方式,分类决策依赖于对物体各部分相对位置的综合性判断,从而在完全卷积的共享计算框架下,统一了分类所需的不变性与定位所需的敏感性。
本章小结
本节我们深入探讨了R-FCN产生的背景及其核心设计思路。我们认识到,目标检测技术的发展始终围绕着精度与速度的平衡,以及如何更好地适配基础网络架构的演进。R-FCN的创新在于它敏锐地抓住了检测网络中“位置敏感”与“位置不变”这一对核心矛盾,并通过全卷积化和位置敏感编码的巧妙设计,近乎完美地解决了ResNet等现代网络在检测任务中遇到的适配难题,为后续的端到端、全卷积化检测器设计提供了重要思路。
今天,R-FCN 已被 Mask R-CNN、Cascade R-CNN 等两阶段后续以及 YOLO 系列、DETR 等单阶段/Transformer 检测器取代;但“位置敏感分值图 + 位置敏感池化”把位置信息显式编码进全卷积网络的思路,仍是理解全卷积检测器的重要一环。
📋 行动清单
- 厘清传统Faster R-CNN结构与全卷积网络(如ResNet)直接结合时,在结构和性能上分别会遇到什么问题。
- 理解“位置敏感性”与“位置不变性”这两个概念在图像分类和目标检测任务中的不同需求及其矛盾点。
- 掌握R-FCN中“位置敏感分值图”和“位置敏感RoI池化”两个关键组件的设计动机与工作流程,能够阐述它们是如何实现全卷积化检测的。
—— 小象教研组