深度学习---图像分割

图像分割

1 传统的基于CNN的分割方法缺点?

传统的基于CNN的分割方法:为了对一个像素分类,使用该像素周围的一个图像块作为CNN的输入,用于训练与预测,这种方法主要有几个缺点:
  
1)存储开销大,例如,对每个像素使用15 * 15的图像块,然后不断滑动窗口,将图像块输入到CNN中进行类别判断,因此,需要的存储空间随滑动窗口的次数和大小急剧上升;
  
2)效率低下,相邻像素块基本上是重复的,针对每个像素块逐个计算卷积,这种计算有很大程度上的重复;
  
3)像素块的大小限制了感受区域的大小,通常像素块的大小比整幅图像的大小小很多,只能提取一些局部特征,从而导致分类性能受到限制。
  
而全卷积网络(FCN)则是从抽象的特征中恢复出每个像素所属的类别。即从图像级别的分类进一步延伸到像素级别的分类。

2. FCN改变了什么?

对于一般的分类CNN网络,如VGG和Resnet,都会在网络的最后加入一些全连接层,经过softmax后就可以获得类别概率信息。但是这个概率信息是1维的,即只能标识整个图片的类别,不能标识每个像素点的类别,所以这种全连接方法不适用于图像分割。
而FCN提出可以把后面几个全连接都换成卷积,这样就可以获得一张2维的feature map,后接softmax获得每个像素点的分类信息,从而解决了分割问题,,

3. FCN网络结构?

FCN对图像进行像素级的分类,从而解决了语义级别的图像分割(semantic segmentation)问题。与经典的CNN在卷积层之后使用全连接层得到固定长度的特征向量进行分类(全联接层+softmax输出)不同,FCN可以接受任意尺寸的输入图像,采用反卷积层对最后一个卷积层的feature map进行上采样, 使它恢复到输入图像相同的尺寸,从而可以对每个像素都产生了一个预测, 同时保留了原始输入图像中的空间信息, 最后在上采样的特征图上进行逐像素分类。

4. 全卷积网络举例?

通常CNN网络在卷积层之后会接上若干个全连接层, 将卷积层产生的特征图(feature map)映射成一个固定长度的特征向量。以AlexNet为代表的经典CNN结构适合于图像级的分类和回归任务,因为它们最后都得到整个输入图像的一个概率向量,比如AlexNet的ImageNet模型输出一个1000维的向量表示输入图像属于每一类的概率(softmax归一化)。
(1)在CNN中, 猫的图片输入到AlexNet, 得到一个长为1000的输出向量, 表示输入图像属于每一类的概率, 其中在“tabby cat”这一类统计概率最高, 用来做分类任务。
  
(2)FCN与CNN的区别在于把CNN最后的全连接层转换成卷积层,输出的是一张已经Label好的图片, 而这个图片就可以做语义分割。
  
(3)CNN的强大之处在于它的多层结构能自动学习特征,并且可以学习到多个层次的特征: 较浅的卷积层感知域较小,学习到一些局部区域的特征;较深的卷积层具有较大的感知域,能够学习到更加抽象一些的特征。高层的抽象特征对物体的大小、位置和方向等敏感性更低,从而有助于识别性能的提高, 所以我们常常可以将卷积层看作是特征提取器。

5. 全连接层和卷积层如何相互转化?

两者相互转换的可能性:
  
全连接层和卷积层之间唯一的不同就是卷积层中的神经元只与输入数据中的一个局部区域连接,并且在卷积列中的神经元共享参数。然而在两类层中,神经元都是计算点积,所以它们的函数形式是一样的。因此,将此两者相互转化是可能的:
  
(1)对于任一个卷积层,都存在一个能实现和它一样的前向传播函数的全连接层。权重矩阵是一个巨大的矩阵,除了某些特定块,其余部分都是零。而在其中大部分块中,元素都是相等的。
  
(2)任何全连接层都可以被转化为卷积层。比如VGG16中第一个全连接层是25088 * 4096的数据尺寸,将它转化为512 * 7 * 7 * 4096的数据尺寸,即一个K=4096的全连接层,输入数据体的尺寸是7 * 7 * 512,这个全连接层可以被等效地看做一个F=7, P=0, S=1, K=4096 的卷积层。换句话说,就是将滤波器的尺寸设置为和输入数据体的尺寸一致7 * 7, 这样输出就变为1 * 1 * 4096, 本质上和全连接层的输出是一样的。
  
输出激活数据体深度是由卷积核的数目决定的(K=4096)。
  
在两种变换中,将全连接层转化为卷积层在实际运用中更加有用。假设一个卷积神经网络的输入是227x227x3的图像,一系列的卷积层和下采样层将图像数据变为尺寸为7x7x512的激活数据体, AlexNet的处理方式为使用了两个尺寸为4096的全连接层,最后一个有1000个神经元的全连接层用于计算分类评分。我们可以将这3个全连接层中的任意一个转化为卷积层:
  
(1)第一个连接区域是[7x7x512]的全连接层,令其滤波器尺寸为F=7,K=4096,这样输出数据体就为[1x1x4096]。
  
(2)第二个全连接层,令其滤波器尺寸为F=1,K=4096,这样输出数据体为[1x1x4096]。
  
(3)最后一个全连接层也做类似的,令其F=1,K=1000,最终输出为[1x1x1000]。

6. 为什么传统CNN的输入图片是固定大小?

对于CNN,一幅输入图片在经过卷积和pooling层时,这些层是不关心图片大小的。比如对于一个卷积层,outputsize = (inputsize - kernelsize) / stride + 1,它并不关心inputsize多大,对于一个inputsize大小的输入feature map,滑窗卷积,输出outputsize大小的feature map即可。pooling层同理。但是在进入全连接层时,feature map(假设大小为n×n)要拉成一条向量,而向量中每个元素(共n×n个)作为一个结点都要与下一个层的所有结点(假设4096个)全连接,这里的权值个数是4096×n×n,而我们知道神经网络结构一旦确定,它的权值个数都是固定的,所以这个n不能变化,n是conv5的outputsize,所以层层向回看,每个outputsize都要固定,那每个inputsize都要固定,因此输入图片大小要固定。

7. 把全连接层的权重W重塑成卷积层的滤波器有什么好处?

这样的转化可以在单个向前传播的过程中, 使得卷积网络在一张更大的输入图片上滑动,从而得到多个输出(可以理解为一个label map)。
  
比如: 我们想让224×224尺寸的浮窗,以步长为32在384×384的图片上滑动,把每个经停的位置都带入卷积网络,最后得到6×6个位置的类别得分, 那么通过将全连接层转化为卷积层之后的运算过程为:
  
如果224×224的输入图片经过卷积层和下采样层之后得到了[7x7x512]的数组,那么,384×384的大图片直接经过同样的卷积层和下采样层之后会得到[12x12x512]的数组, 然后再经过上面由3个全连接层转化得到的3个卷积层,最终得到[6x6x1000]的输出((12 – 7)/1 + 1 = 6), 这个结果正是浮窗在原图经停的6×6个位置的得分。
  
一个确定的CNN网络结构之所以要固定输入图片大小,是因为全连接层权值数固定,而该权值数和feature map大小有关, 但是FCN在CNN的基础上把1000个结点的全连接层改为含有1000个1×1卷积核的卷积层,经过这一层,还是得到二维的feature map,同样我们也不关心这个feature map大小, 所以对于输入图片的size并没有限制。

(1)全连接层转化为全卷积层 : 在传统的CNN结构中,前5层是卷积层,第6层和第7层分别是一个长度为4096的一维向量,第8层是长度为1000的一维向量,分别对应1000个不同类别的概率。FCN将这3层表示为卷积层,卷积核的大小 (通道数,宽,高) 分别为 (4096,1,1)、(4096,1,1)、(1000,1,1)。看上去数字上并没有什么差别,但是卷积跟全连接是不一样的概念和计算过程,使用的是之前CNN已经训练好的权值和偏置,但是不一样的在于权值和偏置是有自己的范围,属于自己的一个卷积核。
  
(2)CNN中输入的图像大小是统一固定成227x227大小的图像,第一层pooling后为55x55,第二层pooling后图像大小为27x27,第五层pooling后的图像大小为13x13, 而FCN输入的图像是H * W大小,第一层pooling后变为原图大小的1/2,第二层变为原图大小的1/4,第五层变为原图大小的1/8,第八层变为原图大小的1/16。
  
(3)经过多次卷积和pooling以后,得到的图像越来越小,分辨率越来越低。其中图像到H/32 * W/32的时候图片是最小的一层时,所产生图叫做heatmap热图,热图就是我们最重要的高维特征图,得到高维特征的heatmap之后就是最重要的一步也是最后的一步对原图像进行upsampling,把图像进行放大几次到原图像的大小。
  
相较于使用被转化前的原始卷积神经网络对所有36个位置进行迭代计算优化模型,然后再对36个位置做预测,使用转化后的卷积神经网络进行一次前向传播计算要高效得多,因为36次计算都在共享计算资源。这一技巧在实践中经常使用,通常将一张图像尺寸变得更大,然后使用变换后的卷积神经网络来对空间上很多不同位置进行评价得到分类评分,然后在求这些分值的平均值。

8.反卷积层理解

Upsampling的操作可以看成是反卷积(deconvolutional),卷积运算的参数和CNN的参数一样是在训练FCN模型的过程中通过bp算法学习得到。反卷积层也是卷积层,不关心input大小,滑窗卷积后输出output。deconv并不是真正的deconvolution(卷积的逆变换),最近比较公认的叫法应该是transposed convolution,deconv的前向传播就是conv的反向传播。
  
反卷积参数: 利用卷积过程filter的转置(实际上就是水平和竖直方向上翻转filter)作为计算卷积前的特征图。

9. FCN缺点

1)得到的结果还是不够精细。进行8倍上采样虽然比32倍的效果好了很多,但是上采样的结果还是比较模糊和平滑,对图像中的细节不敏感。
  
(2)对各个像素进行分类,没有充分考虑像素与像素之间的关系。忽略了在通常的基于像素分类的分割方法中使用的空间规整(spatial regularization)步骤,缺乏空间一致性。

10. U-Net

卷积网络被大规模应用在分类任务中,输出的结果是整个图像的类标签。然而,在许多视觉任务,尤其是生物医学图像处理领域,目标输出应该包括目标类别的位置,并且每个像素都应该有类标签。另外,在生物医学图像往往缺少训练图片。所以,Ciresan等人训练了一个卷积神经网络,用滑动窗口提供像素的周围区域(patch)作为输入来预测每个像素的类标签。这个网络有两个优点:
第一,输出结果可以定位出目标类别的位置;
第二,由于输入的训练数据是patches,这样就相当于进行了数据增广,解决了生物医学图像数量少的问题。
  
但是,这个方法也有两个很明显缺点。
  
第一,它很慢,因为这个网络必须训练每个patch,并且因为patch间的重叠有很多的冗余(冗余会造成什么影响呢?卷积核里面的W,就是提取特征的权重,两个块如果重叠的部分太多,这个权重会被同一些特征训练两次,造成资源的浪费,减慢训练时间和效率,虽然说会有一些冗余,训练集大了,准确率不就高了吗?可是你这个是相同的图片啊,重叠的东西都是相同的,举个例子,我用一张相同的图片训练20次,按照这个意思也是增大了训练集啊,可是会出现什么结果呢,很显然,会导致过拟合,也就是对你这个图片识别很准,别的图片就不一定了)。
  
第二,定位准确性和获取上下文信息不可兼得。大的patches需要更多的max-pooling层这样减小了定位准确性(为什么?因为你是对以这个像素为中心的点进行分类,如果patch太大,最后经过全连接层的前一层大小肯定是不变的,如果你patch大就需要更多的pooling达到这个大小,而pooling层越多,丢失信息的信息也越多;小的patches只能看到很小的局部信息,包含的背景信息不够。
  
这篇论文建立了一个更好全卷积方法。我们定义和扩展了这个方法它使用更少的训练图片但产生更精确的分割。
(1) 使用全卷积神经网络。(全卷积神经网络就是卷积取代了全连接层,全连接层必须固定图像大小而卷积不用,所以这个策略使得,你可以输入任意尺寸的图片,而且输出也是图片,所以这是一个端到端的网络。)
  
(2) 左边的网络是收缩路径:使用卷积和maxpooling。
  
(3) 右边的网络是扩张路径:使用上采样产生的特征图与左侧收缩路径对应层产生的特征图进行concatenate操作。(pooling层会丢失图像信息和降低图像分辨率且是不可逆的操作,对图像分割任务有一些影响,对图像分类任务的影响不大,为什么要做上采样?因为上采样可以补足一些图片的信息,但是信息补充的肯定不完全,所以还需要与左边的分辨率比较高的图片相连接起来(直接复制过来再裁剪到与上采样图片一样大小),这就相当于在高分辨率和更抽象特征当中做一个折衷,因为随着卷积次数增多,提取的特征也更加有效,更加抽象,上采样的图片是经历多次卷积后的图片,肯定是比较高效和抽象的图片,然后把它与左边不怎么抽象但更高分辨率的特征图片进行连接)。
  
(4) 最后再经过两次反卷积操作,生成特征图,再用两个1X1的卷积做分类得到最后的两张heatmap,例如第一张表示的是第一类的得分,第二张表示第二类的得分heatmap,然后作为softmax函数的输入,算出概率比较大的softmax类,选择它作为输入给交叉熵进行反向传播训练。
U-Net模型的代码实现

def get_unet():
    inputs = Input((img_rows, img_cols, 1))
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(inputs)
    conv1 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv1)
    pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)
    # pool1 = Dropout(0.25)(pool1)
    # pool1 = BatchNormalization()(pool1)

    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(pool1)
    conv2 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv2)
    pool2 = MaxPooling2D(pool_size=(2, 2))(conv2)
    # pool2 = Dropout(0.5)(pool2)
    # pool2 = BatchNormalization()(pool2)

    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(pool2)
    conv3 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv3)
    pool3 = MaxPooling2D(pool_size=(2, 2))(conv3)
    # pool3 = Dropout(0.5)(pool3)
    # pool3 = BatchNormalization()(pool3)

    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(pool3)
    conv4 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv4)
    pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)
    # pool4 = Dropout(0.5)(pool4)
    # pool4 = BatchNormalization()(pool4)

    conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(pool4)
    conv5 = Conv2D(512, (3, 3), activation='relu', padding='same')(conv5)

    up6 = concatenate([Conv2DTranspose(256, (2, 2), strides=(
        2, 2), padding='same')(conv5), conv4], axis=3)
    # up6 = Dropout(0.5)(up6)
    # up6 = BatchNormalization()(up6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(up6)
    conv6 = Conv2D(256, (3, 3), activation='relu', padding='same')(conv6)

    up7 = concatenate([Conv2DTranspose(128, (2, 2), strides=(
        2, 2), padding='same')(conv6), conv3], axis=3)
    # up7 = Dropout(0.5)(up7)
    # up7 = BatchNormalization()(up7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(up7)
    conv7 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv7)

    up8 = concatenate([Conv2DTranspose(64, (2, 2), strides=(
        2, 2), padding='same')(conv7), conv2], axis=3)
    # up8 = Dropout(0.5)(up8)
    # up8 = BatchNormalization()(up8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(up8)
    conv8 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv8)

    up9 = concatenate([Conv2DTranspose(32, (2, 2), strides=(
        2, 2), padding='same')(conv8), conv1], axis=3)
    # up9 = Dropout(0.5)(up9)
    # up9 = BatchNormalization()(up9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(up9)
    conv9 = Conv2D(32, (3, 3), activation='relu', padding='same')(conv9)

    # conv9 = Dropout(0.5)(conv9)

    conv10 = Conv2D(1, (1, 1), activation='sigmoid')(conv9)

    model = Model(inputs=[inputs], outputs=[conv10])

    model.compile(optimizer=Adam(lr=1e-5),
                  loss=dice_coef_loss, metrics=[dice_coef])

    return model

11. SegNet

可训练的图像分割引擎,包含一个encoder网络,一个对应的decoder网络,衔接像素级分类层,解码网络与VGG16的13层卷积层相同。解码网络是将低分辨率的编码特征图映射到全分辨率的特征图。解码网络使用最大池化层的池化索引进行非线性上采样,上采样过程就不需要学习。上采样得到的稀疏图与可训练的滤波器卷积得到致密的特征图。
  
使用池化层索引进行上采样的优势:
  
1)提升边缘刻画度;
  
2)减少训练的参数;
  
3)这种上采样模式可以包含到任何编码-解码网络中。
SegNet网络结构如图1所示,Input为输入图片,Output为输出分割的图像,不同颜色代表不同的分类。语义分割的重要性就在于不仅告诉你图片中某个东西是什么,而且告知你他在图片的位置。我们可以看到是一个对称网络,由中间绿色pooling层与红色upsampling层作为分割,左边是卷积提取高维特征,并通过pooling使图片变小,SegNet作者称为Encoder,右边是反卷积(在这里反卷积与卷积没有区别)与upsampling,通过反卷积使得图像分类后特征得以重现,upsampling使图像变大,SegNet作者称为Decoder,最后通过Softmax,输出不同分类的最大值。这就是大致的SegNet过程,下面对这个过程里面使用到的方法进行介绍。
  
编码网络与滤波器族卷积得到特征图,进行BN,ReLU,最大池化。最大池化是为了获得空间小位移的平移不变。最大池化和下采样损失了边缘细节,因此,在编码过程中保存边缘信息很重要。考虑到内存原因,只保存最大池化索引,如最大特征值的位置。
解码网络使用保存的最大池化索引上采样,得到稀疏的特征图,将特征图与可训练的解码滤波器族卷积得到致密的特征图。之后进行BN。高维的特征图输入soft-max层,对每个像素进行分类,得到每个像素属于K类的概率。 图3中右边是FCN的解码技术,FCN对编码的特征图进行降维,降维后输入到解码网络,解码网络中,上采样使用反卷积实现,上采样的特征图与降维的编码图进行element-wise add得到最终的解码特征图。FCN解码模型需要存储编码特征图,在嵌入式设备中内存紧张。
  
SegNet的Encoder过程中,卷积的作用是提取特征,SegNet使用的卷积为same卷积(详见卷积神经网络CNN(1)),即卷积后不改变图片大小;在Decoder过程中,同样使用same卷积,不过卷积的作用是为upsampling变大的图像丰富信息,使得在Pooling过程丢失的信息可以通过学习在Decoder得到。SegNet中的卷积与传统CNN的卷积并没有区别。

12. 空洞卷积(Dilated Convolutions)

在图像分割领域,图像输入到CNN(典型的网络比如FCN[3])中,FCN先像传统的CNN那样对图像做卷积再pooling,降低图像尺寸的同时增大感受野,但是由于图像分割预测是pixel-wise的输出,所以要将pooling后较小的图像尺寸upsampling到原始的图像尺寸进行预测(upsampling一般采用deconv反卷积操作,deconv可参见知乎答案如何理解深度学习中的deconvolution networks?),之前的pooling操作使得每个pixel预测都能看到较大感受野信息。因此图像分割FCN中有两个关键,一个是pooling减小图像尺寸增大感受野,另一个是upsampling扩大图像尺寸。在先减小再增大尺寸的过程中,肯定有一些信息损失掉了,那么能不能设计一种新的操作,不通过pooling也能有较大的感受野看到更多的信息呢?答案就是dilated conv。
  
以前的CNN主要问题总结:
  
(1)Up-sampling / pooling layer
  
(2)内部数据结构丢失;空间层级化信息丢失。
  
(3)小物体信息无法重建 (假设有四个pooling layer 则 任何小于 2^4 = 16 pixel 的物体信息将理论上无法重建。)

13. RefineNet

esidual convolution unit就是普通的去除了BN的residual unit;

  
Multi-resolution fusion是先对多输入的feature map都用一个卷积层进行adaptation(都化到最小的feature map的shape),再上采样再做element-wise的相加。注意如果是像RefineNet-4那样的单输入block这一部分就直接pass了;

  
Chained residual pooling中的ReLU对接下来池化的有效性很重要,还可以使模型对学习率的变化没这么敏感。这个链式结构能从很大范围区域上获取背景context。另外,这个结构中大量使用了identity mapping这样的连接,无论长距离或者短距离的,这样的结构允许梯度从一个block直接向其他任一block传播。

  
Output convolutions就是输出前再加一个RCU。

14. PSPNet

场景解析对于无限制的开放词汇和不同场景来说是具有挑战性的.本文使用文中的pyramid pooling module实现基于不同区域的上下文集成,提出了PSPNet,实现利用上下文信息的能力进行场景解析。
  
作者认为,FCN存在的主要问题是没有采取合适的策略来用全局的信息,本文的做法就是借鉴SPPNet来设计了PSPNet解决这个问题。
  
很多State-of-the-art的场景解析框架都是基于FCN的.基于CNN的方法能够增强动态物体的理解,但是在无限制词汇和不同场景中仍然面临挑战.
FCN认为右侧框中是汽车,但是实际上是船,如果参考上下文的先验知识,就会发现左边是一个船屋,进而推断是框中是船.FCN存在的主要问题就是不能利用好全局的场景线索。

  
对于尤其复杂的场景理解,之前都是采用空间金字塔池化来做的,和之前方法不同(为什么不同,需要参考一下经典的金字塔算法),本文提出了pyramid scene parsing network(PSPNet)。
  
本文的主要贡献如下:
  
(1) 提出了PSPNet在基于FCN的框架中集成困难的上下文特征
  
(2) 通过基于深度监督误差开发了针对ResNet的高效优化策略
  
(3) 构建了一个用于state-of-the-art的场景解析和语义分割的实践系统(具体是什么?)
  
通过观察FCN的结果,发现了如下问题:
  
(1) 关系不匹配(Mismatched Relationship)
  
(2) 易混淆的类别(Confusion Categories)
  
(3) 不显眼的类别(Inconspicuous Classes)
  
总结以上结果发现,以上问题部分或者全部与上下文关系和全局信息有关系,

15. DeepLab系列

1.DeepLabv1

DeepLab 是结合了深度卷积神经网络(DCNNs)和概率图模型(DenseCRFs)的方法。
  
在实验中发现 DCNNs 做语义分割时精准度不够的问题,根本原因是 DCNNs 的高级特征的平移不变性,即高层次特征映射,根源于重复的池化和下采样。
  
针对信号下采样或池化降低分辨率,DeepLab 是采用的 atrous(带孔)算法扩展感受野,获取更多的上下文信息。
  
分类器获取以对象中心的决策是需要空间变换的不变性,这天然地限制了 DCNN 的定位精度,DeepLab 采用完全连接的条件随机场(CRF)提高模型捕获细节的能力。
  
除空洞卷积和 CRFs 之外,论文使用的 tricks 还有 Multi-Scale features。其实就是 U-Net 和 FPN 的思想,在输入图像和前四个最大池化层的输出上附加了两层的 MLP,第一层是 128 个 3×3 卷积,第二层是 128 个 1×1 卷积。最终输出的特征与主干网的最后一层特征图融合,特征图增加 5×128=640 个通道。
  
实验表示多尺度有助于提升预测结果,但是效果不如 CRF 明显。
  
论文模型基于 VGG16,在 Titan GPU 上运行速度达到了 8FPS,全连接 CRF 平均推断需要 0.5s ,在 PASCAL VOC-2012 达到 71.6% IOU accuracy。

2. DeepLabv2

DeepLabv2 是相对于 DeepLabv1 基础上的优化。DeepLabv1 在三个方向努力解决,但是问题依然存在:特征分辨率的降低、物体存在多尺度,DCNN 的平移不变性。
  
因 DCNN 连续池化和下采样造成分辨率降低,DeepLabv2 在最后几个最大池化层中去除下采样,取而代之的是使用空洞卷积,以更高的采样密度计算特征映射。
  
物体存在多尺度的问题,DeepLabv1 中是用多个 MLP 结合多尺度特征解决,虽然可以提供系统的性能,但是增加特征计算量和存储空间。
  
论文受到 Spatial Pyramid Pooling (SPP) 的启发,提出了一个类似的结构,在给定的输入上以不同采样率的空洞卷积并行采样,相当于以多个比例捕捉图像的上下文,称为 ASPP (atrous spatial pyramid pooling) 模块。
  
DCNN 的分类不变形影响空间精度。DeepLabv2 是采样全连接的 CRF 在增强模型捕捉细节的能力。
  
论文模型基于 ResNet,在 NVidia Titan X GPU 上运行速度达到了 8FPS,全连接 CRF 平均推断需要 0.5s ,在耗时方面和 DeepLabv1 无差异,但在 PASCAL VOC-2012 达到 79.7 mIOU。

3.DeepLabv3

好的论文不止说明怎么做,还告诉为什么。DeepLab 延续到 DeepLabv3 系列,依然是在空洞卷积做文章,但是探讨不同结构的方向。
  
1.Image Pyramid:将输入图片放缩成不同比例,分别应用在 DCNN 上,将预测结果融合得到最终输出。
  
2.Encoder-Decoder:利用 Encoder 阶段的多尺度特征,运用到 Decoder 阶段上恢复空间分辨率,代表工作有 FCN、SegNet、PSPNet 等工。
  
3.Deeper w. Atrous Convolution:在原始模型的顶端增加额外的模块,例如 DenseCRF,捕捉像素间长距离信息。
  
4.Spatial Pyramid Pooling:空间金字塔池化具有不同采样率和多种视野的卷积核,能够以多尺度捕捉对象。
  
DeepLabv1-v2 都是使用带孔卷积提取密集特征来进行语义分割。但是为了解决分割对象的多尺度问题,DeepLabv3 设计采用多比例的带孔卷积级联或并行来捕获多尺度背景。
  
此外,DeepLabv3 将修改之前提出的带孔空间金字塔池化模块,该模块用于探索多尺度卷积特征,将全局背景基于图像层次进行编码获得特征,取得 state-of-art 性能,在 PASCAL VOC-2012 达到 86.9 mIOU。

4. DeepLabv3+

语义分割关注的问题:
  
1、 实例对象多尺度问题。
  
2、 因为深度网络存在stride=2的层,会导致feature分辨率下降,从而导致预测精度降低,而造成的边界信息丢失问题。
  
deeplab V3新设计的aspp结构解决了问题1,deeplab v3+主要目的在于解决问题2。
  
问题2 可以使用空洞卷积替代更多的pooling层来获取分辨率更高的feature。但是feature分辨率更高会极大增加运算量。以deeplab v3使用的resnet101为例,stride=16将造成后面9层feature变大,后面9层的计算量变为原来的22=4倍大。stride=8则更为恐怖,后面78层的计算量都会变大很多。
  
解决方案:1、编解码器结构;2 Modified Aligned Xception
在deeplabv3基础上加入解码器。A是aspp结构,其中8x的上采样可以看做是一个解码器。B是编解码结构,它集合了高层和底层的特征。C就是本文采取的结构。
  
方法:
  
(1)Encoder-Decoder with Atrous Convolution
编码器采用deeplabv3。
  
解码器部分:先从低层级选一个feature,将低层级的feature用1 * 1的卷积进行通道压缩(原本为256通道,或者512通道),目的在于减少低层级的比重。作者认为编码器得到的feature具有更丰富的信息,所以编码器的feature应该有更高的比重。 这样做有利于训练。
  
再将编码器的输出上采样,使其分辨率与低层级feature一致。举个例子,如果采用resnet conv2 输出的feature,则这里要
4上采样。将两种feature连接后,再进行一次3 * 3的卷积(细化作用),然后再次上采样就得到了像素级的预测。后面的实验结果表明这种结构在 stride=16 时既有很高的精度速度又很快。stride=8相对来说只获得了一点点精度的提升,但增加了很多的计算量。
  
(2)Modified Aligned Xception
  
Xception主要采用了deepwish seperable convolution来替换原来的卷积层。简单的说就是这种结构能在更少参数更少计算量的情况下学到同样的信息。这边则是考虑将原来的resnet-101骨架网换成xception。
红色部分为修改
  
更多层:重复8次改为16次(基于MSRA目标检测的工作)。
  
将原来简单的pool层改成了stride为2的deepwish seperable convolution。
  
额外的RELU层和归一化操作添加在每个 3 × 3 depthwise convolution之后(原来只在1 * 1卷积之后)

16. Mask-R-CNN

其中黑色部分为原来的Faster-RCNN,红色部分为在Faster网络上的修改:
  
1)将ROI Pooling层替换成了ROIAlign;
  
2)添加并列的FCN层(Mask层);
  
先来概述一下Mask-RCNN的几个特点(来自于PaperMask R-CNN的Abstract):
  
1)在边框识别的基础上添加分支网络,用于语义Mask识别;
  
2)训练简单,相对于Faster仅增加一个小的Overhead,可以跑到5FPS;
  
3)可以方便的扩展到其他任务,比如人的姿态估计等;
  
4)不借助Trick,在每个任务上,效果优于目前所有的 single-model entries;包括 COCO 2016 的Winners。

17. Mask-RCNN 技术要点

1.技术要点1 - 强化的基础网络
  
通过ResNeXt-101+FPN用作特征提取网络,达到state-of-the-art的效果。
  
2.技术要点2 - ROIAlign
  
采用ROIAlign替代RoiPooling(改进池化操作)。引入了一个插值过程,先通过双线性插值到1414,再pooling到77,很大程度上解决了仅通过Pooling直接采样带来的Misalignment对齐问题。
  
PS: 虽然 Misalignment 在分类问题上影响并不大,但在 Pixel 级别的 Mask 上会存在较大误差。
  
后面我们把结果对比贴出来(Table2 c & d),能够看到 ROIAlign 带来较大的改进,可以看到,Stride 越大改进越明显。
  
3.技术要点3 - Loss Function
  
每个ROIAlign对应K * m^2维度的输出。K对应类别个数,即输出K个mask,m对应池化分辨率(7 * 7)。Loss函数定义:
L m a s k ( C l s k ) = S i g m o i d ( C l s k ) Lmask(Cls_k)=Sigmoid(Cls_k) Lmask(Clsk)=Sigmoid(Clsk)
  
L m a s k ( C l s k ) = S i g m o i d ( C l s k ) Lmask(Cls_k) = Sigmoid (Cls_k) Lmask(Clsk)=Sigmoid(Clsk),平均二值交叉熵 (average binary cross-entropy)Loss,通过逐像素的 Sigmoid 计算得到。
  
Why K个mask?通过对每个 Class 对应一个Mask可以有效避免类间竞争(其他Class不贡献Loss)。
通过结果对比来看(Table2 b),也就是作者所说的 Decouple 解耦,要比多分类的Softmax效果好很多。
  
另外,作者给出了很多实验分割效果,就不都列了,只贴一张和FCIS的对比图(FCIS出现了Overlap的问题)

18. CNN在基于弱监督学习的图像分割中的应用

最近基于深度学习的图像分割技术一般依赖于卷积神经网络CNN的训练,训练过程中需要非常大量的标记图像,即一般要求训练图像中都要有精确的分割结果。
  
对于图像分割而言,要得到大量的完整标记过的图像非常困难,比如在ImageNet数据集上,有1400万张图有类别标记,有50万张图给出了bounding box,但是只有4460张图像有像素级别的分割结果。对训练图像中的每个像素做标记非常耗时,特别是对医学图像而言,完成对一个三维的CT或者MRI图像中各组织的标记过程需要数小时。
  
如果学习算法能通过对一些初略标记过的数据集的学习就能完成好的分割结果,那么对训练数据的标记过程就很简单,这可以大大降低花在训练数据标记上的时间。这些初略标记可以是:
  
1、只给出一张图像里面包含哪些物体,
  
2、给出某个物体的边界框,
  
3、对图像中的物体区域做部分像素的标记,例如画一些线条、涂鸦等(scribbles)。

19. Scribble标记

香港中文大学的Di Lin提出了一个基于Scribble标记的弱监督学习方法。Scribble是一个很方便使用的标记方法,因此被用得比较广泛。如下图,只需要画五条线就能完成对一副图像的标记工作。
ScribbleSup分为两步,第一步将像素的类别信息从scribbles传播到其他未标记的像素,自动完成所有的训练图像的标记工作; 第二步使用这些标记图像训练CNN。在第一步中,该方法先生成super-pxels, 然后基于graph cut的方法对所有的super-pixel进行标记。
Graph Cut的能量函数为:

∑ i ψ i ( y i ∣ X , S ) + ∑ i , j ψ i j ( y i , y j , X ) \sum_{i}\psi _i\left(y_i|X,S\right)+\sum_{i,j}\psi_{ij}\left(y_i,y_j,X\right) iψi(yiX,S)+i,jψij(yi,yj,X)

  
在这个graph中,每个super-pixel是graph中的一个节点,相接壤的super-pixel之间有一条连接的边。这个能量函数中的一元项包括两种情况,一个是来自于scribble的,一个是来自CNN对该super-pixel预测的概率。整个最优化过程实际上是求graph cut能量函数和CNN参数联合最优值的过程:

∑ i ψ i s c r ( y i ∣ X , S ) + ∑ i − l o g P ( y i ∣ X , θ ) + ∑ i , j ψ i j ( y i , y j ∣ X ) \sum_{i}\psi _i^{scr}\left(y_i|X,S\right)+\sum _i-logP\left(y_i| X,\theta\right)+\sum_{i,j}\psi _{ij}\left(y_i,y_j|X\right) iψiscr(yiX,S)+ilogP(yiX,θ)+i,jψij(yi,yjX)

  
上式的最优化是通过交替求 Y Y Y θ \theta θ 的最优值来实现的。文章中发现通过三次迭代就能得到比较好的结果。

20. 图像级别标记

UC Berkeley的Deepak Pathak使用了一个具有图像级别标记的训练数据来做弱监督学习。训练数据中只给出图像中包含某种物体,但是没有其位置信息和所包含的像素信息。该文章的方法将image tags转化为对CNN输出的label分布的限制条件,因此称为 Constrained convolutional neural network (CCNN).
该方法把训练过程看作是有线性限制条件的最优化过程:

m i n i m i z e θ , P D ( P ( X ) ∣ ∣ Q ( X ∣ θ ) ) s u b j e c t → A P → ⩾ b → , ∑ X P ( X ) = 1 \underset{\theta ,P}{minimize}\qquad D(P(X)||Q(X|\theta ))\\ subject\to\qquad A\overrightarrow{P} \geqslant \overrightarrow{b},\sum_{X}^{ }P(X)=1 θ,PminimizeD(P(X)∣∣Q(Xθ))subjectAP b ,XP(X)=1
  

其中的线性限制条件来自于训练数据上的标记,例如一幅图像中前景类别像素个数期望值的上界或者下界(物体大小)、某个类别的像素个数在某图像中为0,或者至少为1等。该目标函数可以转化为为一个loss function,然后通过SGD进行训练。
实验中发现单纯使用Image tags作为限制条件得到的分割结果还比较差,在PASCAL VOC 2012 test数据集上得到的mIoU为35.6%,加上物体大小的限制条件后能达到45.1%,如果再使用bounding box做限制,可以达到54%。FCN-8s可以达到62.2%,可见弱监督学习要取得好的结果还是比较难。

21. DeepLab+bounding box+image-level labels**

Google的George Papandreou 和UCLA的Liang-Chieh Chen等在DeepLab的基础上进一步研究了使用bounding box和image-level labels作为标记的训练数据。使用了期望值最大化算法(EM)来估计未标记的像素的类别和CNN的参数。
对于image-level标记的数据,我们可以观测到图像的像素值和图像级别的标记 ,但是不知道每个像素的标号,因此把 y y y当做隐变量。使用如下的概率图模式:
P ( x , y , z ; θ ) = P ( x ) ( ∏ m = 1 M P ( y m ∣ x ; θ ) ) P ( z ∣ y ) P\left ( x,y,z;\theta \right ) = P\left ( x \right )\left (\prod_{m=1}^{M} P\left ( y_m|x;\theta \right )\right )P\left ( z|y \right ) P(x,y,z;θ)=P(x)(m=1MP(ymx;θ))P(zy)
这篇论文是通过EM算法来学习模型的参数 θ \theta θ,具体推导过程可参考原论文。
对于给出bounding box标记的训练图像,该方法先使用CRF对该训练图像做自动分割,然后在分割的基础上做全监督学习。通过实验发现,单纯使用图像级别的标记得到的分割效果较差,但是使用bounding box的训练数据可以得到较好的结果,在VOC2012 test数据集上得到mIoU 62.2%。另外如果使用少量的全标记图像和大量的弱标记图像进行结合,可以得到与全监督学习(70.3%)接近的分割结果(69.0%)。

22. 统一的框架

Wisconsin-Madison大学的Jia Xu提出了一个统一的框架来处理各种不同类型的弱标记:图像级别的标记、bounding box和部分像素标记如scribbles。该方法把所有的训练图像分成共计 n n n个super-pixel,对每个super-pixel提取一个 d d d维特征向量。因为不知道每个super-pixel所属的类别,相当于无监督学习,因此该方法对所有的super-pixel做聚类,使用的是最大间隔聚类方法(max-margin clustering, MMC),该过程的最优化目标函数是:

m i n W , H 1 2 t r ( W T W ) + λ ∑ p = 1 n ∑ c = 1 C ξ ( w c ; x p ; h p c ) \underset{W,H}{min} \qquad \frac{1}{2}tr\left ( W^TW \right ) + \lambda\sum_{p=1}^{n}\sum_{c=1}^{C}\xi \left ( w_c;x_p;h_p^c \right) W,Hmin21tr(WTW)+λp=1nc=1Cξ(wc;xp;hpc)

  
在这个目标函数的基础上,根据不同的弱标记方式,可以给出不同的限制条件,因此该方法就是在相应的限制条件下求最大间隔聚类。

该方法在Siftflow数据集上得到了比较好的结果,比state-of-the-art的结果提高了10%以上。

  
小结:在弱标记的数据集上训练图像分割算法可以减少对大量全标记数据的依赖,在大多数应用中会更加贴合实际情况。弱标记可以是图像级别的标记、边框和部分像素的标记等。训练的方法一般看做是限制条件下的最优化方法。另外EM算法可以用于CNN参数和像素类别的联合求优。

23. DenseNet

卷积神经网络结构的设计主要朝着两个方向发展,一个是更宽的网络(代表:GoogleNet、VGG),一个是更深的网络(代表:ResNet)。但是随着层数的加深会出现一个问题——梯度消失,这将会导致网络停止训练。到目前为止解决这个问题的思路基本都是在前后层之间加一个identity connections(short path)。
由上图中可知Resnet是做值的相加(也就是add操作),通道数是不变的。而DenseNet是做通道的合并(也就是Concatenation操作),就像Inception那样。从这两个公式就可以看出这两个网络的本质不同。此外DensetNet的前面一层输出也是后面所有层的输入,这也不同于ResNet残差网络。

1*1卷积核的目的:减少输入的特征图数量,这样既能降维减少计算量,又能融合各个通道的特征。我们将使用BottleNeck Layers的DenseNet表示为DenseNet-B。(在论文的实验里,将1×1×n小卷积里的n设置为4k,k为每个H产生的特征图数量)

DenseNet网络的优点包括:

  • 减轻了梯度消失
  • 加强了feature的传递
  • 更有效地利用了feature
  • 一定程度上较少了参数数量
  • 一定程度上减轻了过拟合
  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值