• 从FCN/U-Net看CNN图像语义分割经典方法


    从FCN/U-Net看CNN图像语义分割经典方法

    FCN论文地址:FCN paper

    FCN原作代码:FCN github

    图像语义分割(Semantic Segmentation)是图像处理和是机器视觉技术中关于图像理解的重要一环,也是 AI 领域中一个重要的分支。语义分割即是对图像中每一个像素点进行分类,确定每个点的类别(如属于背景、人或车等),从而进行区域划分。目前,语义分割已经被广泛应用于自动驾驶、无人机落点判定等场景中。

    img

    而截止目前,CNN已经在图像分类分方面取得了巨大的成就,涌现出如VGG和Resnet等网络结构,并在ImageNet中取得了好成绩。CNN的强大之处在于它的多层结构能自动学习特征,并且可以学习到多个层次的特征:

    1. 较浅的卷积层感知域较小,学习到一些局部区域的特征;
    2. 较深的卷积层具有较大的感知域,能够学习到更加抽象一些的特征。

    这些抽象特征对物体的大小、位置和方向等敏感性更低,从而有助于分类性能的提高。这些抽象的特征对分类很有帮助,可以很好地判断出一幅图像中包含什么类别的物体。图像分类是图像级别的!

    img

    与分类不同的是,语义分割需要判断图像每个像素点的类别,进行精确分割。图像语义分割是像素级别的!但是由于CNN在进行convolution和pooling过程中丢失了图像细节,即feature map size逐渐变小,所以不能很好地指出物体的具体轮廓、指出每个像素具体属于哪个物体,无法做到精确的分割。

    针对这个问题,Jonathan Long等人提出了Fully Convolutional Networks(FCN)用于图像语义分割。自从提出后,FCN已经成为语义分割的基本框架,后续算法其实都是在这个框架中改进而来。

    FCN改变了什么?

    对于一般的分类CNN网络,如VGG和Resnet,都会在网络的最后加入一些全连接层,经过softmax后就可以获得类别概率信息。但是这个概率信息是1维的,即只能标识整个图片的类别,不能标识每个像素点的类别,所以这种全连接方法不适用于图像分割。

    img

    而FCN提出可以把后面几个全连接都换成卷积,这样就可以获得一张2维的feature map,后接softmax获得每个像素点的分类信息,从而解决了分割问题,如图4。

    img

    FCN结构

    整个FCN网络基本原理如图5(只是原理示意图)

    1. image经过多个conv和+一个max pooling变为pool1 feature,宽高变为1/2
    2. pool1 feature再经过多个conv+一个max pooling变为pool2 feature,宽高变为1/4
    3. pool2 feature再经过多个conv+一个max pooling变为pool3 feature,宽高变为1/8
    4. ......
    5. 直到pool5 feature,宽高变为1/32。

    img

    那么:

    1. 对于FCN-32s,直接对pool5 feature进行32倍上采样获得$32 imes $upsampled feature,再对$32 imes $upsampled feature每个点做softmax prediction获得$32 imes $upsampled feature prediction(即分割图)。
    2. 对于FCN-16s,首先对pool5 feature进行2倍上采样获得(2 imes)upsampled feature,再把pool4 feature和(2 imes)upsampled feature逐点相加,然后对相加的feature进行16倍上采样,并softmax prediction,获得(16 imes)upsampled feature prediction。
    3. 对于FCN-8s,首先进行pool4+(2 imes)upsampled feature逐点相加,然后又进行pool3+(2 imes)upsampled逐点相加,即进行更多次特征融合。具体过程与16s类似,不再赘述。

    作者在原文种给出3种网络结果对比,明显可以看出效果:FCN-32s < FCN-16s < FCN-8s,即使用多层feature融合有利于提高分割准确性

    img

    什么是上采样?

    说了半天,到底什么是上采样?

    实际上,上采样(upsampling)一般包括2种方式:

    1. Resize,如双线性插值直接缩放,类似于图像缩放(这种方法在原文中提到)
    2. Deconvolution,也叫Transposed Convolution

    什么是Resize就不多说了,这里解释一下Deconvolution。

    对于一般卷积,输入蓝色(4 imes 4)矩阵,卷积核大小(3 imes 3)。当设置卷积参数pad=0,stride=1时,卷积输出绿色(2 imes 2)矩阵,如下图。

    img

    而对于反卷积,相当于把普通卷积反过来,输入蓝色(2 imes 2)矩阵(周围填0变成(6 imes 6)),卷积核大小还是(3 imes 3)。当设置反卷积参数pad=0,stride=1时输出绿色(4 imes 4)矩阵,如下图,这相当于完全将图4倒过来(其他更多卷积示意图点这里)。

    img

    传统的网络是subsampling的,对应的输出尺寸会降低;upsampling的意义在于将小尺寸的高维度feature map恢复回去,以便做pixelwise prediction,获得每个点的分类信息。

    img

    上采样在FCN网络中的作用如上图,明显可以看到经过上采样后恢复了较大的pixelwise feature map(其中最后一个层21-dim是因为PACSAL数据集有20个类别+Background)。这其实相当于一个Encode-Decode的过程。

    具体的FCN网络结构,可以在fcn caffe prototext中查到,建议使用Netscope查看网络结构。这里解释里面的难点:

    • 为了解决图像过小后 1/32 下采样后输出feature map太小情况,FCN原作者在第一个卷积层conv1_1加入pad=100。
    layer {
      name: "conv1_1"
      type: "Convolution"
      bottom: "data"
      top: "conv1_1"
      param {
        lr_mult: 1
        decay_mult: 1
      }
      param {
        lr_mult: 2
        decay_mult: 0
      }
      convolution_param {
        num_output: 64
        pad: 100             # pad=100
        kernel_size: 3
        stride: 1
      }
    }
    

    考虑如果不在conv1_1加入pad=100,会发生什么?

    假设输入图像高度为h。由于VGG中缩小输出feature map只在pooling层,经过每个pooling后输出高度变为:

    [egin{matrix}pool1&h^1=(h-2)/2+1=h/2\pool2&h^2=(h^1-2)/2+1=h/2^2\...&...\pool5&h^5=(h^4-2)/2+1=h/2^5end{matrix} ]

    很明显,feature map的尺寸缩小了32倍,接下来是fc6卷积层:

    layer {
      name: "fc6"
      type: "Convolution"
      bottom: "pool5"
      top: "fc6"
      param {
        lr_mult: 1
        decay_mult: 1
      }
      param {
        lr_mult: 2
        decay_mult: 0
      }
      convolution_param {
        num_output: 4096
        pad: 0
        kernel_size: 7
        stride: 1
      }
    }
    

    [egin{matrix}fc6&h^6=(h^5-7)/1+1=(h-192)/2^5end{matrix} ]

    如果不在conv1_1加入pad=100,那么对于小于(192 imes 192)的输入图像,在反卷积恢复尺寸前已经feature map size = 0!所以在conv1_1添加pad=100的方法,解决输入图像大小的问题(但是实际也引入很大的噪声)。

    • 由于FCN在conv1_1加入pad=100,同时fc6卷积层也会改变feature map尺寸,那么真实的网络就不可能像原理图3那样“完美1/2”。

    那么在特征融合的时候,如何保证逐点相加的feature map是一样大的呢?这就要引入crop层了。以fcn-8s score_pool4c为例:

    layer {
      name: "score_pool4c"
      type: "Crop"
      bottom: "score_pool4"  # 需要裁切的blob
      bottom: "upscore2"     # 用于指示裁切尺寸的blob,和输出blob一样大
      top: "score_pool4c"    # 输出blob
      crop_param {
        axis: 2
        offset: 5
      }
    }
    

    在caffe中,存储数据的方式为 blob = [num, channel, height, width],与pytorch一样

    1. 而score_pool4c设置了axis=2,相当于从第2维(index start from 0!)往后开始裁剪,即裁剪height和width两个维度,同时不改变num和channel纬度
    2. 同时设置crop在height和width纬度的开始点为offset=5

    不妨定义:

    crop_w = upscore2 blob width
    crop_h = upscore2 blob height
    

    用Python语法表示,相当于score_pool4c层的输出为:

    score_pool4c = score_pool4[:, :, 5:5+crop_h, 5:5+crop_w]
    

    刚好相当于从score_pool4中切出upscore2大小!这样就可以进行逐点相加的特征融合了。

    U-Net

    U-Net原作者官网

    U-Net是原作者参加ISBI Challenge提出的一种分割网络,能够适应很小的训练集(大约30张图)。U-Net与FCN都是很小的分割网络,既没有使用空洞卷积,也没有后接CRF,结构简单。

    img

    整个U-Net网络结构如上图,类似于一个大大的U字母:首先进行Conv+Pooling下采样;然后Deconv反卷积进行上采样,crop之前的低层feature map,进行融合;然后再次上采样。重复这个过程,直到获得输出(388 imes 388 imes 2)的feature map,最后经过softmax获得output segment map。总体来说与FCN思路非常类似。图7

    为何要提起U-Net?是因为U-Net采用了与FCN完全不同的特征融合方式:拼接!

    img

    与FCN逐点相加不同,U-Net采用将特征在channel维度拼接在一起,形成更“厚”的特征。所以:

    语义分割网络在特征融合时也有2种办法:

    1. FCN式的逐点相加,对应caffe的EltwiseLayer层,对应tensorflow的tf.add()
    2. U-Net式的channel维度拼接融合,对应caffe的ConcatLayer层,对应tensorflow的tf.concat()

    相比其他大型网络,FCN/U-Net还是蛮简单的,就不多废话了。

    总结一下,CNN图像语义分割也就基本上是这个套路:

    1. 下采样+上采样:Convlution + Deconvlution/Resize
    2. 多尺度特征融合:特征逐点相加/特征channel维度拼接
    3. 获得像素级别的segement map:对每一个像素点进行判断类别

    看,即使是更复杂的DeepLab v3+依然也是这个基本套路。

    img

    本文来自博客园,作者:甫生,转载请注明原文链接:https://www.cnblogs.com/fusheng-rextimmy/p/15456153.html

  • 相关阅读:
    NKOJ P3051浇花
    Linux-Shell脚本编程-学习-2-Linux基本命令
    Linux-Shell脚本编程-学习-1-Linux基本命令
    Ubuntu下使用Git_6
    Ubuntu下使用Git_5
    电脑优化,提速
    Ubuntu下使用Git_4
    Ubuntu下使用Git_3
    Ubuntu下使用Git_2
    Ubuntu下使用Git_1
  • 原文地址:https://www.cnblogs.com/fusheng-rextimmy/p/15456153.html
Copyright © 2020-2023  润新知