一、FCN
利用深度学习做语义分割的开山之作,作者以vgg网路作为基础,将全连接层转为了卷积层,为了能更好的处理边缘信息,使用了多尺度的融合,将FCN-8s,16s, 32s进行融合。
缺点:1、不是端到端的,需要使用条件随机场做后处理。
2、虽然使用了多尺度融合,但是对边缘信息的处理不够理想。
3、没有考虑像素之间的相关性,也即是它们的空间位置信息。


二、SegNet
为了解决FCN对细节,特别是边缘信息不敏感的问题,作者使用了带坐标的池化,即进行最大池化操作的时候记录最大数值的位置。
而且在上采样的过程中,直接使用记录的池化位置来填充恢复到对应的位置。这样既可以保持边缘位置而不造成偏移,同时又可以减少计算量。在反池化之后,连续接3个卷积来恢复更多的信息。
在论文中,作者同样使用了多层的特征融合。

基于tensorflow网络结构代码:
#####################
# Downsampling path #
#####################
net = conv_block(inputs, 64)
net = conv_block(net, 64)
net = slim.pool(net, [2, 2], stride=[2, 2], pooling_type='MAX')
skip_1 = net
net = conv_block(net, 128)
net = conv_block(net, 128)
net = slim.pool(net, [2, 2], stride=[2, 2], pooling_type='MAX')
skip_2 = net
net = conv_block(net, 256)
net = conv_block(net, 256)
net = conv_block(net, 256)
net = slim.pool(net, [2, 2], stride=[2, 2], pooling_type='MAX')
skip_3 = net
net = conv_block(net, 512)
net = conv_block(net, 512)
net = conv_block(net, 512)
net = slim.pool(net, [2, 2], stride=[2, 2], pooling_type='MAX')
skip_4 = net
net = conv_block(net, 512)
net = conv_block(net, 512)
net = conv_block(net, 512)
net = slim.pool(net, [2, 2], stride=[2, 2], pooling_type='MAX')
#####################
# Upsampling path #
#####################
net = conv_transpose_block(net, 512)
net = conv_block(net, 512)
net = conv_block(net, 512)
net = conv_block(net, 512)
if has_skip:
net = tf.add(net, skip_4)
net = conv_transpose_block(net, 512)
net = conv_block(net, 512)
net = conv_block(net, 512)
net = conv_block(net, 256)
if has_skip:
net = tf.add(net, skip_3)
net = conv_transpose_block(net, 256)
net = conv_block(net, 256)
net = conv_block(net, 256)
net = conv_block(net, 128)
if has_skip:
net = tf.add(net, skip_2)
net = conv_transpose_block(net, 128)
net = conv_block(net, 128)
net = conv_block(net, 64)
if has_skip:
net = tf.add(net, skip_1)
net = conv_transpose_block(net, 64)
net = conv_block(net, 64)
net = conv_block(net, 64)
三、U-Net
经典的语义分割结构,在医学领域使用广泛。作者通过将下采样的特征图直接和上采样的特征图进行concat的操作来获取更多的信息,也可以改善FCN中丢失细节的问题。
u-net的结构可以使用较少的样本进行训练,得到不错的效果,但是这种结构计算量较大,比较消耗计算资源。

四、DeepLab v1
对标准的分类网络来说,连续进行池化操作,可以在不断缩小特征图尺寸的同时增大感受野,让图像从低层的细节信息向高层的语义信息转化,从而完成对物体类别的分辨。
很多人包括论文中都解释说,网络的这种特性是对目标的空间信息不敏感的表现。
我个人认为这种说法不太准确,因为我们在对网络的某些卷积层进行可视化的时候可以发现,网络对目标的位置是敏感的。只不过在逐渐池化的过程中,由于特征图缩小到一定程度之后,目标在逐渐富集之后都基本会占据整张特征图,从而可以稳定的给出分类结果,而这也给了我们一种对目标空间信息不敏感的错觉。
其实,语义分割的问题是细节信息与语义信息的矛盾问题,我们必须对目标正确分类的同时,还要从像素级别确定它的位置。
我们知道卷积的感受野很小(即使对于高层的特征层来说,实际的感受野也并没有我们想象中的那么大),可以很容易的解决信息问题,但是对于某一部分有时候无法通过细节确定它的分类,而必须结合其他位置的信息。这就要求更大的感受野。
而本文提出的空洞卷积可以在保持分辨率的同时获得更大的感受野,而且空洞卷积还避免了细节信息的丢失,简直是一举多得,我认为这也是其成功的原因。
另外,空洞卷积避免了分辨率的减小,那么也就减少了反卷积的使用,无形中又大大减少了计算量。
注:回想常规的语义分割做法,在encoder阶段实际上是解决的分类问题(即获得语义信息),decoder阶段解决的是目标的具体定位问题(即重构细节信息)。

五、DeepLab v2
我们知道,同一种类别的物体有可能存在多种不同的尺寸,这会为语义分割的效果带来挑战。
在传统的方法中,一般是通过图像金字塔来解决这个问题,而在目标检测中,我们是用特征金字塔来代替图像金字塔,在保证了检测精度的同时又提高了检测效率。
在本文中,作者受SPP的启发提出了ASPP的结构来解决目标检测的多尺度问题。
(回忆一下SPP,其实这个结构是为了解决两阶段目标检测中第二个阶段输入的特征图大小不一致而提出的。当然,后来其被简化版的roi pooling取代,而roi pooling又被精度更高的roi align代替。)
ASPP的做法是对同一张特征图,用不同扩张率的空洞分别去处理,因为这些卷积的感受野不同,因此它们提取到的信息也会有所不同,然后再把结果进行融合。
注:1、仔细想一下,这种做法和特征金字塔很像。但不同的是特征金字塔在不同的特征层分别进行检测,而ASPP最终还是把所有的特征图融合起来进行分割。
那么,这里我们是否可以借鉴特征金字塔的做法,对不同扩张率的空洞卷积的结果分别做分割,而在最终的Heat map上对它们进行合并呢?具体合并的方式可以考虑两种不同的方法:(1)是直接进行融合。(2)是借鉴nms的做法进行合并。
2、ASPP也可以考虑用在目标检测的框架中,结合在FNP里面可以尝试一下效果会不会更好。

六、DeepLab v3
相比较于之前的v2版本,v3在一些细节地方做了改进:(1)增加了Batch Normalization。 (2)改进了ASPP的结构:增加了1x1的卷积;增加了image pooling;带洞卷积的扩张率减少为了3个,分别是:6, 12, 18;改变了特征组合的方式:在v2中是把不同扩张率的结果直接相加,这里的方法是把(2)中的所有结果进行concat。(3)改变了对groundtruth的处理方式:在v2中,是将groundth缩小output_stride倍,让其和输出的特征图大小一致,然后计算loss;而这里的做法是对特征图上采样output_stride倍,让其恢复到groundth的大小。(4)增大了输入图片的尺寸(用来保证大扩张率带洞卷积的结果。(5)去除了CRFs。
其实,v3最主要的地方还是优化了ASPP的结构,因为作者发现当带洞卷积的扩张率太大,而图片(或者特征图)太小或者卷积滑动到靠近边缘的位置的时候,3x3卷积的边缘位置都是0,有效区域实际只有中间的部分,这个时候3x3卷积就退化为了1x1卷积。

网友评论