目录
参考资料
论文:
Fully Convolutional Networks for Semantic Segmentation
语义分割综述:
史上最全语义分割综述(FCN,UNet,SegNet,Deeplab,ASPP…)
博客:
第1章 前言
对于一般的分类CNN网络,如 VGG
和 Resnet
,都会在网络的最后加入一些全连接层,经过softmax后就可以获得类别概率信息。但是这个概率信息是1维的,即只能标识整个图片的类别,不能标识每个像素点的类别,所以这种全连接方法不适用于图像分割。
而 FCN
提出可以把后面几个全连接都换成卷积,这样就可以获得一张2维的feature map,后接softmax层获得每个像素点的分类信息,从而解决了分割问题。
如上图所示:
- (1)在CNN中, 猫的图片输入到
AlexNet
, 得到一个长为1000的输出向量, 表示输入图像属于每一类的概率, 其中在“tabby cat”这一类统计概率最高, 用来做分类任务。 - (2)FCN与CNN的区别在于把CNN最后的全连接层转换成卷积层,输出的是一张已经带有标签的图片, 而这个图片就可以做语义分割。
- (3)CNN的强大之处在于它的多层结构能自动学习特征,并且可以学习到多个层次的特征:
- 较浅的卷积层感知域较小,学习到一些局部区域的特征;
- 较深的卷积层具有较大的感知域,能够学习到更加抽象一些的特征。
- 高层的抽象特征对物体的大小、位置和方向等敏感性更低,从而有助于识别性能的提高, 所以我们常常可以将卷积层看作是特征提取器。
第2章 FCN网络
2.1 FCN结构
FCN对图像进行像素级的分类,从而解决了 语义级别的图像分割(semantic segmentation)
问题。与经典的CNN在卷积层之后使用全连接层得到固定长度的特征向量进行分类(全联接层+softmax输出)不同,FCN可以接受任意尺寸的输入图像,采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸,从而可以对每个像素都产生了一个预测, 同时保留了原始输入图像中的空间信息, 最后在上采样的特征图上进行逐像素分类。下图是语义分割所采用的全卷积网络(FCN)的结构示意图:
CNN中输入的图像大小是统一固定成 227 × 227 227\times227 227×227 大小的图像,第一层pooling后为 55 × 55 55\times55 55×55 ,第二层pooling后图像大小为 27 × 27 27\times27 27×27,第五层pooling后的图像大小为 13 × 13 13\times13 13×13 ;
而FCN输入的图像是 H × W H \times W H×W 大小,第一层pooling后变为原图大小的 1 2 \frac{1}{2} 21 ,第二层变为原图大小的 1 4 \frac{1}{4} 41 ,第五层变为原图大小的 1 8 \frac{1}{8} 81 ,第八层变为原图大小的 1 16 \frac{1}{16} 161 。
经过多次卷积和pooling以后,得到的图像越来越小,分辨率越来越低。其中图像到
H
2
×
W
2
\frac{H}{2} \times \frac{W}{2}
2H×2W 的时候图片是最小的一层时,所产生图叫做 heatmap热图
,热图就是我们最重要的高维特征图,得到高维特征的heatmap之后就是最重要的一步也是最后的一步对原图像进行 upsampling
,把图像进行放大几次到原图像的大小。
2.2 UnPooling、Unsampling、Deconvolution
(1)UnPooling
是填充0:
(2)Unsampling
是填充相同的值:
(3)Deconvolution
意为转置卷积或反卷积,其实就是正向卷积的逆过程。
- 正向卷积按照对应的
stride
、Padding
等参数,将Input_size
变为Out_size
; - 反向卷积按照对应的
stride
、Padding
等参数,将上述的Out_size
变为Input_size
;
转置卷积操作后特征图的大小可以通过如下公式计算:
H
o
u
t
=
(
H
i
n
−
1
)
×
s
t
r
i
d
e
[
0
]
−
2
×
p
a
d
d
i
n
g
[
0
]
+
k
e
r
n
e
l
_
s
i
z
e
[
0
]
W
o
u
t
=
(
W
i
n
−
1
)
×
s
t
r
i
d
e
[
1
]
−
2
×
p
a
d
d
i
n
g
[
1
]
+
k
e
r
n
e
l
_
s
i
z
e
[
1
]
H_{out}=(H_{in}−1)×stride[0]−2×padding[0]+kernel\_size[0] \\ W_{out}=(W_{in}−1)×stride[1]−2×padding[1]+kernel\_size[1]
Hout=(Hin−1)×stride[0]−2×padding[0]+kernel_size[0]Wout=(Win−1)×stride[1]−2×padding[1]+kernel_size[1]
其中stride[0]表示高度方向的stride,padding[0]表示高度方向的padding,kernel_size[0]表示高度方向的kernel_size,索引[1]都表示宽度方向上的。
通过上面公式可以看出padding越大,输出的特征矩阵高、宽越小,你可以理解为正向卷积过程中进行了padding然后得到了特征图,现在使用转置卷积还原到原来高、宽后要把之前的padding减掉,就是和正向卷积一一对应,只不过反过来计算而已。
2.3 跳级(skip)结构
对CNN的结果做处理,得到了 dense prediction
,而作者在试验中发现,得到的分割结果比较粗糙,**所以考虑加入更多前层的细节信息,也就是把倒数第几层的输出和最后的输出做一个fusion,实际上也就是 加和
**:
实验表明,这样的分割结果更细致更准确。在逐层fusion的过程中,做到第三行再往下,结果又会变差,所以作者做到这里就停了。
第3章 模型训练细节
(1)用 AlexNet
, VGG16
或者 GoogleNet
训练好的模型做初始化,在这个基础上做 fine-tuning
,全部都 fine-tuning
,只需在末尾加上 upsampling
,参数的学习还是利用CNN本身的反向传播原理;
(2)采用 whole image(整张图像)
做训练,不进行patchwise sampling(类似于感兴趣区域);
(3)对分类网络之外的卷积层做全零初始化,随机初始化在性能和收敛上没有优势。
(4)反卷积参数初始化为 双线性插值
。
(5)最后一层反卷积固定位bilinear插值不做学习。
下面为具体的训练过程:
(1)输入可为任意尺寸图像彩色图像;
(2)输出与输入尺寸相同;
(3)深度为:20类目标+背景=21;
(4)模型基于AlexNet。
- 蓝色:卷积层。
- 绿色:Max Pooling层。
- 黄色:求和运算,使用逐元素相加,把三个不同深度的预测结果进行融合:较浅的结果更为精细,较深的结果更为鲁棒。
- 灰色: 裁剪,在融合之前,使用裁剪层统一两者大小,最后裁剪成和输入相同尺寸输出。
对于不同尺寸的输入图像,各层数据的尺寸(height,width)相应变化,深度(channel)不变。
(1)以经典的 AlexNet
分类网络为初始化,最后两级是全连接(红色),参数弃去不用。
(2)从特征小图预测分割小图,之后直接升采样为大图。
(3)升采样分为两次完成(橙色×2), 在第二次升采样前,把第4个pooling层(绿色)的预测结果(蓝色)融合进来。使用跳级结构提升精确性。
(4)升采样分为三次完成(橙色×3), 进一步融合了第3个pooling层的预测结果。
第4章 FCN的缺点
(1)得到的结果还是不够精细。进行8倍上采样虽然比32倍的效果好了很多,但是上采样的结果还是比较模糊和平滑,对图像中的细节不敏感。
(2)对各个像素进行分类,没有充分考虑像素与像素之间的关系。忽略了在通常的基于像素分类的分割方法中使用的空间规整(spatial regularization)步骤,缺乏空间一致性。
第5章 如何理解FCN网络在目标检测中的应用
5.1 特征图尺寸变化
我们首先不考虑通道数,来看一下上面网络中的特征图尺寸的具体变化,下图绿色为卷积核,橙色为特征图:
从上图中,我们可以看到,输入是一个 14 × 14 14\times14 14×14 大小的图片,经过一个 5 × 5 5\times5 5×5 的卷积(不填充)后,得到一个 10 × 10 10\times10 10×10 的特征图,然后再经过一个 2 × 2 2\times2 2×2 的池化后,尺寸缩小到一半变成 5 × 5 5\times5 5×5 的特征图,再经过一个 5 × 5 5\times5 5×5 的卷积后,特征图变为 1 × 1 1\times1 1×1 ,接着后面再进行两次 1 × 1 1\times1 1×1 的卷积(类似全连接操作),最终得到一个 1 × 1 1\times1 1×1 的输出结果。
那么该 1 × 1 1\times1 1×1 的输出结果,就代表最前面 14 × 14 14\times14 14×14 图像区域的分类情况,如果对应到上面的猫狗和背景的分类任务,那么最后输出的结果应该是一个 1 × 3 1\times3 1×3 的矩阵,其中每个值代表 14 × 14 14\times14 14×14 的输入图片中对应类别的分类得分。
5.2 不同尺寸的输入图片
FCN可以接收任意尺寸的输入,我们接下来看一个大一点的图片输入进来,会得到什么样的结果,如下图:
我们可以看到上面的图,输入尺寸有原来的 14 × 14 14\times14 14×14 变成了 16 × 16 16\times16 16×16 ,那么经过一个 5 × 5 5\times5 5×5 的卷积(不填充)后,得到一个 12 × 12 12\times12 12×12 的特征图,然后再经过一个 2 × 2 2\times2 2×2 的池化后,尺寸缩小到一半变成 6 × 6 6\times6 6×6 的特征图,再经过一个 5 × 5 5\times5 5×5 的卷积后,特征图变为 2 × 2 2\times2 2×2 ,接着后面再进行两次 1 × 1 1\times1 1×1 的卷积(类似全连接操作),最终得到一个 2 × 2 2\times2 2×2 的输出结果,
5.3 FCN如何对应分类区域
那么该 2 × 2 2\times2 2×2 的输出结果,就代表最前面 16 × 16 16\times16 16×16 图像区域的分类情况,然而,输出是 2 × 2 2\times2 2×2 ,怎么跟前面对应呢?哪一个像素对应哪个区域呢?我们看下图:
我们根据卷积核的作用范围可以推出:
- 输出 2 × 2 2\times2 2×2 中左上角的橙色输出就代表了 16 × 16 16\times16 16×16 中的红色框区域;
- 输出 2 × 2 2\times2 2×2 中右上角的蓝色输出就代表了 16 × 16 16\times16 16×16 中的黄色框区域;
- 输出 2 × 2 2\times2 2×2 中左下角的蓝色输出就代表了 16 × 16 16\times16 16×16 中的黑色框区域;
- 输出 2 × 2 2\times2 2×2 中右下角的蓝色输出就代表了 16 × 16 16\times16 16×16 中的紫色框区域;
其中每个框的大小都是 14 × 14 14\times14 14×14 。也就是说输出的每个值代表了输入图像中的一个区域的分类情况。
5.4 FCN是如何对目标检测进行加速
根据上文,我们知道FCN最后的输出,每个值都对应到输入图像的一个检测区域,也就是说FCN的输出直接反应了对应输入图像检测区域的分类情况。
我们将网络放到一个正常的 28 × 28 × 3 28\times28\times3 28×28×3 的图像上,考虑上特征图的通道数,看下输出值的对应情况:
上图中绿色区域表现了依次通过网络后的特征图尺寸变化情况。因为这是一个猫狗和背景的三分类任务,所以最后输出的图像大小为 8 × 8 × 3 8\times8\times3 8×8×3 ,以输出图像左上角绿色点为例,该点深度为3,对应输入图像的绿色区域,该点的3个值反应了输入图的绿色区域是分类为猫狗还是背景的得分情况。
第6章 Pytorch实现FCN
参考视频:
参考代码: