1、相关参考链接

基本概念:语义分割三维语义分割空洞卷积 两篇综述

最新论文:LEDNet

这里将语义分割网络分为两类:一类是以FCN为代表的“encode-decode”,另一类是以Deeplab为代表的“dilate convolution”(空洞卷积网络)。

语义分割传统方法代码 语义分割fcn_卷积

2、从FCN讲起

FCN(Fully Convolutional Networks for Semantic Segmentation,2014)是语义分割领域的开山之作,顾名思义其特点就是网络中只有卷积层,没有全连接层。它能够实现端到端的像素级别分类,从下图可以大概了解它的整体结构。

语义分割传统方法代码 语义分割fcn_算法_02

实际上对于FCN这样一种元老级别的网络,它的思想要远大于它的实用价值,所以更多的是了解它的创新想法而不是死抠它的性能。FCN的核心思想包括三方面:

  • 使用卷积代替全连接层,使得网络可以适应任意尺寸的输入;
  • 网络后期使用反卷积进行上采样操作,使得网络的输出恢复到输入尺寸大小,从而进行像素级别的分类;
  • 添加 skip connection,联结 low-level 的降采样特征和 high-level 的上采样层,用以优化预测结果。
2.1 网络结构

语义分割传统方法代码 语义分割fcn_算法_03

论文中首先是给出 AlexNet 来讲解FCN的思路,然后对比了 VGG-16、GoogLeNet 作为 backbone 时的效果,最终发现 VGG-16 的 mean IU 值是最高的。上图给出了基于 VGG-16 改造后的FCN详细结构,对比 VGG-16 可以发现,FCN改变的就是最后的三个全连接层以及增加的反卷积和skip connection。

  1. 首先,VGG-16 中使用5个maxpool,每一次使得特征图的尺寸减半。这里我们采用OS(Output stride)来表示特征图与输入图像的大小关系,例如进行一次maxpool之后特征尺寸减小为输入图像的一半,那么 OS=2。
  2. 三个全连接分别被4096个7x7卷积、4096个1x1卷积、num_classes个1x1卷积代替。
  3. 两次skip connection分别与maxpool4、maxpool3的输出特征相连接,因为通道数不一样(最终的通道数为num_classes),所以需要用1x1卷积来调整通道数(图中以num_classes=21为例)。
  4. 这里的连接并不是concat,而是求和;经过反卷积(upsampling)的high-level特征图与经过maxpool、1x1卷积调整之后的low-level特征图理论上具有完全相同的尺寸、通道,所以直接将对应元素求和是可以的。
  5. heatmap总共有num_classes个,每一个都和输入图像拥有相同的尺寸大小,它代表了每一个像素属于一个类的概率,最终取每一个像素的最大概率值作为其归属类。
  6. 虽然有FCN-32s、FCN-16s、FCN-8s三种不同的输出,但是论文证明FCN-8s的精度是最好的,这也体现了skip connection的意义。
2.2 损失函数

因为是像素级别的分类,对于FCN来说每一个像素点就是一个样本。文章将batch_size设置为1,也就是说一次送入一张图,然后对每一个像素的预测类和真实的标签求softmax loss。这里,train和inference稍有区别,inference是直接取每一个像素点的num_classes维向量最大值对应的类,train则是对这个num_classes维向量进行softmax操作,然后求entroy_loss。

这种像素级别的交叉熵损失,将每一个像素点的损失同等对待,但当图像中某一类占主导地位时这种“同一对待”的方式就会显得不太合理。后来的U-Net就给不同的像素损失加以权重辅助,赋予在分割目标边界的像素更高的权重,这种加权损失思想帮助U-Net模型在应对生物学图像的细胞时能够提供边界分明的分割图,从而使得每个细胞个体间的区分更加容易。

另外一种语义分割损失函数的定义就是“Dice coefficient”,它利用heatmap在矩阵级别上与label进行loss的计算,其实跟交叉熵类似,只是交叉熵从像素的通道方向入手,“Dice coefficient”则考虑整体的像素分布。关于“Dice coefficient”的细节内容可以查看上面综述中的第一部分。

2.3 训练数据集

PASCAL VOC 2011中用于语义分割的部分,输入图像尺寸为224。训练分4个阶段进行:

  1. 分类训练,就是不修改 VGG-16 的结构进行训练,最后三个全连接层的参数丢弃;
  2. 训练FCN-32s,这一阶段耗时3天;
  3. 训练FCN-16s,这一阶段耗时1天;
  4. 训练FCN-8s,这一阶段耗时1天。

总结: FCN的反卷积其实和OpenCV中的上采样是一样的道理,只是OpenCV中上采样卷积核的值是固定的,这里上采样卷积核通过学习得到。“卷积+池化”的操作会提取图像中的特征,但是也会损失大量的细节;虽然反卷积可以让feature map的尺寸得以恢复,但是丢失的细节并不能找回来,所以加入low-level的skip connection操作可以看做是找回这些细节。

3、Deeplab V3+

Deeplab V3+ 之前还有三篇文章,但是鉴于Deeplab V3+写的比较详细,不经过前三篇文章的过渡也能基本看懂,除了一些细节、想法的来源等可能是在前面的文章中体现。

3.1 网络结构

语义分割传统方法代码 语义分割fcn_算法_04

Deeplab V3+也采用了“encode-decode”的方式,所以可以对比FCN的网络来看。Deeplab V3+将Deeplab V3作为自己的 encoder,它沿袭了后者的一些创新项,同时也做了一些优化:

  1. ASPP:Deeplab V3+并不是像FCN的VGG-16那样一味地进行“卷积-池化”,它采用的是ASPP结构:A表示的是“Atrous”,就是空洞卷积;SPP指的就是空间金字塔池化。这两者并不是Deeplab V3+的首创,把它们结合起来Deeplab也做过了,Deeplab V3+继承了该部分内容。空洞卷积使用了三次,从上图也能清晰的看到,分别是 语义分割传统方法代码 语义分割fcn_卷积_05,要注意的是这是针对 OS=16 的情况,如果 OS=8 则需要将每一个空洞卷积的 rate 乘以2;池化操作使用的是平均池化。ASPP得到五个尺度相同、通道数不同的特征图,用concat的方式直接拼接后接一个1x1卷积调整通道数。ASPP部分是接在backbone之后的,Deeplab V3+的backbone采用的是ResNet和Xception两种形式,从最终结果上来看Xception要稍微好于ResNet,当然也可以使用其他的backbone形式,比如说轻量化的MobileNet。
  2. Atrous separable convolution:Deeplab V3中采用了 atrous conv(空洞卷积)来提取特征,这个和FCN是完全不同的;它的优势在于可以获得更大的感受野,同时能得到任意分辨率的特征图像。空洞卷积的感受野由参数 rate 控制,当 rate=1 时就和普通卷积没区别。Deeplab V3+在空洞卷积的基础上引入Depthwise separable convolution(通道分离卷积)的思想(先用input_c个3x3x1卷积对每个通道进行计算,然后用output_c个1x1xinput_c卷积做标准卷积计算),在Xception中使用 atrous separable convolution,大大降低了参数量和计算开销,获得了速度和精度上的提升。
  3. Decoder:Deeplab V3+的decoder部分要优于Deeplab V3的双线性插值,这是Deeplab V3+的创新点所在,可以将之前的encoder看作是对上下文信息的编码,decoder则负责将编码的信息解码得到特征。Deeplab V3+的decoder首先采用因子为4的双线性上采样将编码特征从OS=16变为OS=4,然后抽取encoder中具有相同空间分辨率(low-level)的特征层(例如ResNet101中的conv2),做一个skip connection。因为low-level的特征通道数可能比较大(例如256/512),可能会超过输出编码特征的通道数(ResNet101输出 256 channels) 导致训练困难;作者采用1x1卷积对其进行调整,实验证明调整为 channels=48 效果是最好的。skip connection 采用的是concat操作,之后会进行两次3x3卷积,它们是用来优化特征的,实验证明采取2个3x3卷积的效果最好的。在这个卷积之后的特征通道数并不是我们期待的类别数量,所以要用1x1卷积来调整;最后再加上一个上采样操作,将特征尺寸变为和原始图像尺寸一致,这时每个像素就拥有一个代表类概率的向量了。
  4. Xception:受到MSRA提出的 Aligned Xception 的启发,Deeplab V3+对backbone网络 Xception 也做了一些优化。首先,加深网络但是不修改它的“entry flow”部分,为的是保证高效的计算效率;其次,将maxpool操作用atrous separable convolution代替,获取任意分辨率的特征;还有就是,在每个分离卷积后面添加BN和ReLu操作。实验证明,优化后的Xception效果无论是Top1还是Top5都要比ResNet101好。

Deeplab V3+ 定义 encoder 的输入图像空间分辨率和输出图像空间分辨率之比为输出步长(output stride,简写为OS)。一般情况下,图像分类任务中会取 OS=32,表示输出的特征空间分辨率是很小的;但是在语义分割任务中,OS=16 或 OS=8(这在FCN中也能看到),OS如果太大表示丢失的边缘细节会更多,即便进行上采样恢复到输入图像分辨率大小其效果也不会很好。作者通过实验对比说明:OS=16时精度和速度上取得较好的平衡;OS=8时精度更高,但是计算复杂度增加。

3.2 损失函数

Deeplab V3+的损失函数跟FCN是一样的,也是逐像素的交叉熵损失。

语义分割传统方法代码 语义分割fcn_池化_06

3.3 训练数据集

Pretrained用 ImageNet-1K 数据集训练 ResNet101或者优化后的Xception,用来获取dense feature map。对于Xception的预训练还使用了JFT-300M数据集,实验证明用JFT-300M会有1%左右的提升。

接下来的主体网络使用PASCAL VOC 2012数据集训练,包括20类object和1个背景类,训练的输入图像大小为513*513,还做了一定的数据增强。测试集的话作者使用了CityScapes,这是一个大尺度、高分辨率的像素级标注数据集,Deeplab V3+在该数据集上取得了82.1%的成绩。

4、开源代码

4.1 Deeplab-V3+

[tensorflow]

4.2 detectron2

[pytorch]