前言:SegNet语义分割网络是2015年的一篇论文,论文通篇所涉及到的基本理论很少,网络结构也不是很复杂,本文从SegNet的结构着手,分析一下SegNet的工作原理是涉及思想。
SegNet同样是基于FCN,修改VGG-16网络得到的语义分割网络,有两种SegNet,分别为正常版SegNet与贝叶斯版SegNet,同时SegNet作者根据网络的深度提供了一个basic版的SegNet(浅网络)。
HomePage: http://mi.eng.cam.ac.uk/projects/segnet/
SegNet Paper: https://www.computer.org/csdl/trans/tp/2017/12/07803544.html
Dropout as Bayesian Paper: http://mlg.eng.cam.ac.uk/yarin/PDFs/NIPS_2015_deep_learning_uncertainty.pdf
除了上面的一些资料以外,GitHub上有非常多的基于各种不同深度学习开源框架的SegNet实现,包括pytorch、tensorflow、keras等。
SegNet网络结构如上所示,Input为输入图片,Output为输出分割的语义图像,不同颜色代表不同的分类。从上面可以看出,这个网络具有非常好的对称性
语义分割的重要性就在于不仅告诉你图片中某个东西是什么,而且告知它在图片的位置。SegNet是一个对称网络,由中间绿色pooling层与红色upsampling层作为分割,左边是卷积提取高维特征,并通过pooling使图片变小,SegNet作者称为Encoder,右边是反卷积(需要注意的是:在这里反卷积与卷积没有区别,其实就是普通的卷积操作,具体后面会说到的)与upsampling,通过反卷积使得图像分类后特征得以重现,upsampling使图像变大,SegNet作者称为Decoder,最后通过Softmax,输出不同分类的最大值,这就是大致的SegNet过程。
2.1 SegNet中的卷积
首先明确两个观点:
(1)不管是Encoder还是Decoder,SegNet中的卷积全部都是same填充了的,所以都不改变输出特征的大小;大小的改变是通过池化层的上采样、下采样实现的;
(2)在Decoder中,我们称为“反卷积”,实际上,这只是为了使用这个称呼而已,他并不是真正意义上的反卷积,甚至不是转置卷积,他就是一个普通的卷积操作。
SegNet的Encoder过程中,卷积的作用是提取特征,SegNet使用的卷积为same卷积,即卷积后不改变图片大小;在Decoder过程中,同样使用same卷积,不过卷积的作用是为upsampling变大的图像丰富信息,使得在Pooling过程丢失的信息可以通过学习在Decoder得到。SegNet中的卷积与传统CNN的卷积并没有区别。
注意看上面网络的结构:
蓝色部分是:普通Vonv+BN+Relu的标准结构,在Encoder和Decoder里面是一样的;
绿色部分:即下采样过程,即pooling过程,这会是图像变得更小,得到低分辨率的特征图;
红色部分:即上采样过程,即uppooling过程,这会恢复到原来图像的大小,得到高分辨率的特征图,直到恢复原来的图像大小;
重点是绿色部分和红色部分的设计,下面会详细说到。
2.2 关于下采样与上采样的巧妙设计
(1)下采样
其实就是一个2x2的最大池化过程,没什么特别的地方,但是和普通的下采样不一样的是,在SegNet中的Pooling与其他Pooling多了一个index功能,也就是每次Pooling,都会保存通过max选出的权值在2x2 filter中的相对位置,对于图二的6来说,6在粉色2x2 filter中的位置为(1,1),黄色的3的index为(0,0)。同时,从图一可以看到绿色的pooling与红色的upsampling通过pool indices相连,实际上是pooling后的indices输出到对应的upsampling。
(2)上采样
图三: SegNet中基于索引的下采样与上采样的实现
Upsamping就是Pooling的逆过程,Upsamping使得图片变大2倍。我们清楚的知道Pooling之后,每个filter会丢失了3个权重,这些权重是无法复原的,但是在Upsamping层中可以得到在Pooling中相对Pooling filter的位置。所以Upsampling中先对输入的特征图放大两倍,然后把输入特征图的数据根据Pooling indices(即根据之前pooling后保存的位置)放入到对应的那个索引位置,如图三所示,Unpooling对应上述的Upsampling,switch variables对应Pooling indices。
从图三中右边的Upsampling可以知道,2x2的输入,变成4x4的图,但是除了被记住位置的Pooling indices,其他位置的权值为0,因为数据已经被pooling掉了。那这些全部的0怎么处理呢?
事实上这就是Decoder中使用卷积核的总用,即图一中Decoder里面的蓝色部分,其实也就是通过卷积,来重新学习这些缺失的内容,也就是一般的卷积操作,所以在图一中跟随Upsampling层后面的是也就是一般的普通卷积层。
总结:
(1)下采样得到最大值max和它相对应的位置索引(x,y)
(2)上采样通过uppooling回复出采样之前的图像大小,针对填充的全部是0的像素,后面的卷积层会重新学习,得到合适的参数和输出。