DeepLab 是由谷歌团队开发的一系列专为语义分割 (Semantic Segmentation) 任务设计的深度学习模型。语义分割的目标是为图像中的每个像素分配一个类别标签(例如,识别人、车、天空、建筑等)。
语义分割面临的核心挑战
在理解 DeepLabV3+ 之前,我们先要明白传统卷积神经网络 (CNN) 直接用于语义分割时会遇到什么问题:
1.空间分辨率下降:标准的 CNN(如 VGG, ResNet)为了提取高级语义特征,会包含多个池化层 (Pooling) 或带步长 (stride) 的卷积层。这会导致输出的特征图 (feature map) 尺寸远小于原始输入图像,大量的空间细节信息丢失,这对于需要像素级预测的分割任务是致命的。
2.物体多尺度问题:同一类别的物体在图像中可能呈现出不同的大小。例如,一张街景图里,远处的车很小,近处的车很大。模型需要有能力同时识别和分割不同尺度的物体。
3.边界定位不精确:由于深度网络具有空间不变性(spatial invariance),使得模型能很好地进行分类,但这也削弱了其对物体精确边界的定位能力。
DeepLab 系列的核心贡献就是围绕这三个问题提出的创新解决方案。
核心技术一:空洞卷积 (Atrous Convolution)
也被称为扩张卷积 (Dilated Convolution)。它的主要目的是在不增加计算量和参数的情况下,扩大卷积核的感受野 (receptive field),同时保持较高的空间分辨率。
1. 问题根源:池化层的“伤害”
传统的做法是“下采样-上采样”(Encoder-Decoder 结构),比如 FCN (Fully Convolutional Networks)。先通过池化层缩小特征图,提取语义信息,再通过反卷积 (Deconvolution) 或插值 (Interpolation) 将其放大回原始尺寸。但下采样过程造成的信息损失是不可逆的。
2. DeepLab 的解决方案:用空洞卷积替代池化
DeepLab 选择了一条不同的路:直接去掉一部分池化层,以保持特征图的尺寸不被过度压缩。
但是,去掉池化层后,后续卷积层的感受野就会变小,模型将无法捕捉到足够大的上下文信息。怎么办呢?空洞卷积登场了。
3. 空洞卷积如何工作?
空洞卷积引入了一个新的超参数:膨胀率 (dilation rate, r)。它定义了卷积核中各个权重之间的间距。
-
当
r=1时,它就是标准的卷积。 -
当
r>1时,卷积核的元素之间会被插入r-1个“空洞”。
假设我们有一个 3x3 的卷积核:
-
标准卷积 (r=1):卷积核覆盖 3x3 的区域,感受野是 3x3。
-
空洞卷积 (r=2):卷积核的权重被“撑开”,实际覆盖的区域达到了 5x5,但参与计算的权重仍然只有 9 个。它的感受野扩大到了 5x5。
-
空洞卷积 (r=4):感受野进一步扩大到 9x9。
核心技术二:空间金字塔池化
这个模块专门用于解决物体多尺度问题。它的灵感来源于传统的空间金字塔池化 (SPP),但巧妙地用空洞卷积来实现。
1. 设计思想
既然物体有大有小,那么我们就用不同“尺度”的工具去探测它。ASPP 就是并行使用多个不同膨胀率的空洞卷积来处理同一个特征图,从而在多个尺度上捕捉上下文信息。
2. DeepLabv2/v3 中的 ASPP 结构
一个典型的 ASPP 模块通常包含以下几个并行的分支:
一个 1x1 的标准卷积分支。
几个具有不同膨胀率的 3x3 空洞卷积分支(例如,r=1, r=3, r=5)。
一个全局平均池化 (Global Average Pooling) 分支,用于捕捉整个图像的全局上下文信息。
最后,将所有这些并行分支输出的特征图拼接 (concatenate) 在一起,再通过一个 1x1 卷积进行融合,就得到了一个既包含局部细节又包含多尺度上下文信息的强大特征表示。
我们以DeepLab v3中的ASPP模块为例,这是最成熟和经典的版本。它通常接在一个Backbone网络(如ResNet)提取的高级特征之后。
ASPP模块包含5个并行分支,对同一个输入特征图进行处理:
分支一:1x1卷积提供原始尺度的上下文信息,感受野最小。可以看作是捕捉最局部、最基础的特征。它充当了多尺度特征中的一个基础基准。
分支二、三、四:不同膨胀率的3x3空洞卷积:
rate=6:膨胀率较小,感受野中等,适合捕捉中等尺度的物体(如汽车、椅子)
rate=12:膨胀率更大,感受野更大,适合捕捉较大尺度的物体(如建筑物、沙发)。
rate=18:膨胀率最大,感受野极大,适合捕捉全局或极大尺度的物体背景(如天空、道路)。
分支五:图像池化(Image Pooling):
1.全局平均池化(Global Average Pooling, GAP):将整个特征图(H x W)在每个通道上取平均值,得到一个 C x 1 x 1的特征向量。这个向量包含了整个图像的全局上下文信息。
2.1x1卷积:通常会对这个向量进行一个1x1卷积来调整维度。
3.上采样(Upsampling):将 1x1的特征向量上采样(双线性插值)回与输入特征图相同的空间尺寸(H x W)。这个分支提供了真正的全局视野。对于识别非常大的物体(如“天空”这类背景类)至关重要,因为它“看到了”整张图片。它弥补了空洞卷积即使rate很大,其感受野在理论上也可能无法覆盖极端大物体的不足。
如下图所示:
+-----------------------------+
| 输入特征图 (From Backbone) |
+-----------------------------+
|
+-------------------------+-------------------------+
| | | | |
| | | | |
+----------+ +----------------+ +----------------+ +----------------+ +------------------+
| 1x1 卷积 | | Atrous Conv 3x3| | Atrous Conv 3x3| | Atrous Conv 3x3| | 全局平均池化 |
| | | (rate=6) | | (rate=12) | | (rate=18) | | (Image Pooling) |
+----------+ +----------------+ +----------------+ +----------------+ +------------------+
| | | | |
| | | | +----v----+
| | | | | 1x1 卷积|
| | | | +----v----+
| | | | | 上采样 |
| | | | (Upsample)|
| | | | |
+----v----+ +--------v-------+ +--------v-------+ +--------v-------+ +-------v--------+
| 输出 1 | | 输出 2 | | 输出 3 | | 输出 4 | | 输出 5 |
+---------+ +----------------+ +----------------+ +----------------+ +----------------+
| | | | |
| | | | |
+-----------------+-----------------+-----------------+---------------------+
|
+--------------v--------------+
| 沿通道维度拼接 (Concatenate) |
+-----------------------------+
|
+--------------v--------------+
| 1x1 卷积进行融合 |
+-----------------------------+
|
+-----------------------------+
| 最终输出特征图 |
+-----------------------------+
动机:DeepLabv3 的局限与 v3+ 的诞生
要理解 DeepLabv3+,首先要明白 DeepLabv3 有什么不足。
DeepLabv3 通过系统地应用空洞卷积和设计出强大的 ASPP (Atrous Spatial Pyramid Pooling) 模块,成功地在不需要 CRF (条件随机场) 后处理的情况下,生成了语义信息非常丰富、对物体尺度变化鲁棒性很强的分割结果。
然而,它存在一个关键问题:物体边界的分割精度不足。
问题根源在于:为了提取高级语义信息,DeepLabv3 的主干网络(如 ResNet)依然进行了多次下采样。即使使用了空洞卷积来减缓这个过程,其最终输出的特征图分辨率(output_stride = 16 或 8)依然远低于原始输入图像。这意味着,一个 16x16 的像素区域在特征图上被压缩成了一个单点。在最后,模型需要通过简单的双线性插值(Bilinear Interpolation)将这个粗糙的特征图直接放大 16 倍或 8 倍,这个过程非常“暴力”,必然会导致大量空间细节(尤其是物体边缘)的丢失,使得最终的分割结果在物体边界处显得模糊和不精确。
DeepLabv3+ 的核心目标:在保留 DeepLabv3 强大的语义编码能力的同时,引入一种更精细的机制来恢复和锐化物体的边界。
核心架构:Encoder-Decoder(编码器-解码器)
DeepLabv3+ 的解决方案是引入了一个经典且高效的结构:Encoder-Decoder。这个结构在 UNet 等模型中已被证明非常有效。
Encoder (编码器):负责提取丰富的语义信息。它将输入图像编码成一个低空间分辨率但语义信息密集的特征表示。
具体实现:
使用常用的Backbone(如ResNet-101、Xception)提取特征。
使用空洞卷积替代最后几个块中的步长卷积,以防止过度下采样(例如将输出stride从32减少到16)。
将提取到的特征送入增强版的ASPP模块(包含图像池化分支)进行多尺度融合。
输出:一个富含语义信息但分辨率较低(例如是输入图像尺寸的1/16)的特征图。
Decoder (解码器):负责逐步恢复空间信息。它将编码器输出的粗糙语义特征图与来自主干网络浅层的、包含丰富细节的特征图相结合,从而生成一个高分辨率且边界清晰的分割图。
具体步骤:
1.初步上采样:将编码器输出(ASPP的结果)直接进行4倍双线性上采样。
2.获取低级特征:从Backbone的中间层(例如ResNet的conv2块)提取对应的低级特征。这些特征图拥有更高的分辨率(通常是编码器输出的2倍或4倍)和更丰富的细节。
3.特征调整:由于低级特征的通道数通常很多(例如256),但语义性不强,先通过一个1x1卷积进行降维(例如降到48通道),以减少计算量并使其更容易与高级特征融合。
4.特征拼接(Concatenation):将上采样后的高级特征与处理后的低级特征在通道维度上进行拼接。
5.特征融合与微调:对拼接后的特征使用3x3卷积进行融合,进一步提炼信息。最后再进行一次4倍上采样得到最终的分割图。
+---------------+
| 输入图像 |
+---------------+
|
v
+---------------------------------------+
(Encoder) | 主干网络 (如 ResNet-101, Xception) |
| (使用空洞卷积控制 output_stride=16) |
+---------------------------------------+
|
+---------------------------+---------------------------+
| |
v v
+-----------------------+ +-------------------------------------+
| 来自【浅层】的低级特征 | | 来自【深层】的高级特征 |
| (e.g., ResNet conv2) | | (进入ASPP模块前) |
| - 空间分辨率高 | +-------------------------------------+
| - 包含边缘/纹理细节 | |
+-----------------------+ v
| +-------------------------------------+
v | ASPP 模块 |
+-----------------------+ | (捕捉多尺度上下文信息) |
| 1x1 卷积 | +-------------------------------------+
| (降低通道数, e.g., 48) | |
+-----------------------+ v
| +-------------------------------------+
| | 编码器输出 (语义丰富但分辨率低, 1/16) |
| +-------------------------------------+
| |
| v (Decoder开始)
| +------------------------------+
| | 双线性插值上采样 x4 |
| +------------------------------+
| |
+---------------------------------->+<-------------------------------+
|
v
+------------------------------+
| 拼接 (Concatenate) | <-- 这是最关键的融合步骤
+------------------------------+
|
v
+------------------------------+
| 3x3 卷积 (特征融合与细化) |
+------------------------------+
|
v
+------------------------------+
| 双线性插值上采样 x4 |
+------------------------------+
|
v
+------------------------------+
| 最终分割图 (原始尺寸) |
+------------------------------+
实例演示
实例设定
输入图像: 一张 512 x 512 像素的街景彩色照片。其尺寸为 512 x 512 x 3 (高 x 宽 x 通道数)。
任务: 将图像分割成 20 个类别(如:道路、天空、建筑、汽车、行人、树木等)。
网络配置:
主干网络 (Backbone): ResNet-101
输出步幅 (Output Stride): 16
(Output Stride (输出步幅) 是一个关键概念,定义为 输入图像分辨率 / 输出特征图分辨率。)
最终类别数 (N): 20
我们将整个过程分为两个主要部分:编码器 (Encoder) 和 解码器 (Decoder)。
第一部分:编码器 (Encoder) - 提取高级语义特征
第 1步:输入
-
数据:原始街景图片
-
尺寸:
512 x 512 x 3
第 2 步:通过主干网络的浅层
操作: 图像进入 ResNet-101,经过 conv1, pool1, 和 conv2_x (第一个残差块组)。在标准的 ResNet 中,这个阶段的下采样因子是 4(分辨率缩小倍数)。
输出: 得到低级特征图 (Low-level Features)。
尺寸变化: 512 / 4 = 128。通道数变为 256。
输出尺寸: 128 x 128 x 256
信息含义: 这个特征图保留了丰富的空间细节,如物体的边缘、轮廓和纹理,但语义信息较弱(它只知道有“边”,但不知道是“车”的边还是“楼”的边)。
数据去向: 这个特征图将被“暂存”,等待解码器阶段使用。
第 3 步:通过主干网络的深层 (应用空洞卷积)
操作: 数据继续在 ResNet-101 中流动 (conv3_x, conv4_x, conv5_x)。为了将 output_stride 控制在 16,conv4_x 和 conv5_x 中的标准卷积步长被修改为 1,并引入了不同膨胀率 (rate) 的空洞卷积来扩大感受野。最终下采样因子为 16(分辨率缩小倍数)。
输出: 得到准备进入 ASPP 模块的高级特征图。
尺寸变化: 512 / 16 = 32。深层网络的通道数通常很高,在 ResNet-101 中是 2048。
输出尺寸: 32 x 32 x 2048
第 4 步:ASPP 模块
操作: 上一步的 32 x 32 x 2048 特征图被并行送入 ASPP 的 5 个分支中。每个分支最后都输出 256 个通道。
1.1x1 卷积 -> 输出 32 x 32 x 256
2.3x3 空洞卷积 (rate=6) -> 输出 32 x 32 x 256
3.3x3 空洞卷积 (rate=12) -> 输出 32 x 32 x 256
4.3x3 空洞卷积 (rate=18) -> 输出 32 x 32 x 256
5.全局平均池化 -> 1x1x2048 -> 1x1卷积 -> 1x1x256 -> 上采样 -> 32 x 32 x 256
拼接与融合:
-
将 5 个分支的输出沿通道维度拼接:
5 * 256 = 1280。得到一个32 x 32 x 1280的特征图。 -
再通过一个 1x1 卷积进行信息融合和降维。
输出: 得到编码器的最终输出 (高级语义特征)。
输出尺寸: 32 x 32 x 256
信息含义: 这个特征图空间分辨率很低,但每一个像素都蕴含了丰富的、多尺度的上下文信息。它知道图像中 (i,j) 这个位置大概率属于“汽车”类别,但汽车的精确轮廓已经模糊了。
第二部分:解码器 (Decoder) - 恢复空间细节
第 5 步:处理低级特征
操作: 取出在 第 2 步 暂存的低级特征图 (128 x 128 x 256),对其使用一个 1x1 卷积进行降维。
目的: 减少通道数,筛选关键的细节信息,为后续拼接做准备。论文中通常降到 48。
输出: 处理后的低级特征。
输出尺寸: 128 x 128 x 48
第 6步:上采样高级特征
操作: 将 第 3 步 编码器输出的高级语义特征 (32 x 32 x 256) 进行 4 倍双线性插值上采样,使其空间尺寸与处理后的低级特征匹配。
尺寸变化: 32 * 4 = 128。
输出尺寸: 128 x 128 x 256
第 7 步:关键融合 - 拼接
操作: 将第 5 步的输出(细节信息)和第 6 步的输出(语义信息)沿通道维度拼接起来。
尺寸变化: 通道数相加 48 + 256 = 304。
输出尺寸: 128 x 128 x 304
信息含义: 这是模型中最宝贵的特征图,它既有高级语义指导 (知道是什么),又有低级细节定位 (知道在哪里)。
第 8步:特征细化
操作: 使用一个 3x3 卷积对拼接后的特征进行学习和细化,让模型自主学习如何将语义和细节更好地融合。同时通道数可以被进一步调整(例如,降回 256)。
出尺寸: 128 x 128 x 256
第 9 步:最终预测
操作:
1.将第 8 步的细化特征图再进行一次 4 倍上采样,恢复到原始图像尺寸。输出尺寸变为 512 x 512 x 256。
2.最后,使用一个 1x1 卷积,将 256 个通道映射到我们任务所需的 N=20 个类别上。这个 1x1 卷积本质上是一个像素级的分类器。
它是一个 512 x 512 的像素网格,对于网格上的每一个像素,都有一个与之对应的、长度为 256 的特征向量 (feature vector)。这个向量是网络到目前为止学习到的,关于该像素点的所有浓缩信息(比如,它的颜色、纹理、周围环境、语义概念等)。
“映射”的具体计算过程(聚焦于单个像素):
现在,让我们忘记整张 512x512 的图片,只关注其中任意一个像素,比如坐标为 (h, w) 的点。
1.输入: 在 (h, w) 这个点上,我们有一个 256 维的特征向量。我们称之为 V_in = [f₁, f₂, ..., f₂₅₆]。
2.卷积核: 我们有 20 个 1x1x256 的卷积核。我们可以把每个核看作一个 256 维的权重向量。
-
核 1 (用于计算类别1“道路”的得分):
W₁ = [w₁,₁, w₁,₂, ..., w₁,₂₅₆] -
核 2 (用于计算类别2“天空”的得分):
W₂ = [w₂,₁, w₂,₂, ..., w₂,₂₅₆] -
核 20 (用于计算类别20“行人”的得分):
W₂₀ = [w₂₀,₁, w₂₀,₂, ..., w₂₀,₂₅₆]
计算: 1x1 卷积的操作,在单个像素点上,就是输入特征向量 V_in 与每一个卷积核的权重向量 W 进行点积 (Dot Product),并加上一个偏置项 (bias)。
得分_道路 = (V_in • W₁) + b₁ = (f₁*w₁,₁ + f₂*w₁,₂ + ... + f₂₅₆*w₁,₂₅₆) + b₁
得分_行人 = (V_in • W₂₀) + b₂₀ = (f₁*w₂₀,₁ + f₂*w₂₀,₂ + ... + f₂₅₆*w₂₀,₂₅₆) + b₂₀
输出: 经过这 20 次计算,对于 (h, w) 这个像素点,我们就得到了一个 20 维的输出向量 V_out = [得分_道路, 得分_天空, ..., 得分_行人]。
输出: 最终的预测图。
输出尺寸: 512 x 512 x 20
第 10 步:得到分割结果
操作: 对上一步输出的 512 x 512 x 20 的张量,在最后一个维度(通道维度)上执行 argmax 操作。
解释: 对于每一个像素位置 (h, w),我们都有一个长度为 20 的向量,代表该像素属于 20 个类别的概率(或 logits)。argmax 会找到概率最高的那个类别的索引。
最终结果: 一个 512 x 512 的单通道图,其中每个像素的值是 0 到 19 之间的一个整数,代表了该像素的预测类别。这就是我们最终看到的彩色分割结果。
8549

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



