前馈神经网络
图像的表示和数字长方体
图像在计算机中是一堆按顺序排列的数字,数值为0到255,0表示最暗, 255表示最亮。你可以把这堆数字用一个长长的向量来表示。然而这样会失去平面结构的信息,为保留该结构信息,通常选择矩阵的表示方式: 28x28的矩阵。
上图是只有黑白颜色的灰度图,而更普遍的图片表达方式是RGB颜色模型,即红(Red)、绿(Green) 、蓝(Blue)三原色的色光以不同的比例相加,以产生多种多样的色光。
在电脑中,一张图片是数字构成的”长方体” 。可用宽width,高height,深depth来描述,如图。
画面不变性
在决定如何处理”数字长方体”之前,需要清楚所建立的网络拥有什么样的特点。我们知道一个物体不管在画面左侧还是右侧,都会被识别为同一物体,这一特点就是不变性(invariance) ,如下图所示。
我们希望所建立的网络可以尽可能的满足这些不变性特点。为了理解卷积神经网络对这些不变性特点的贡献,我们将用不具备这些不变性特点的前馈神经网络来进行比较。
前馈神经网络的图像识别
方便起见,我们用depth只有1的灰度图来举例。想要完成的任务是:在宽长为4x4的图片中识别是否有下图所示的”横折”。图中,黄色圆点表示值为0的像素,深色圆点表示值为1的像素。我们知道不管这个横折在图片中的什么位置,都会被认为是相同的横折。
若训练前馈神经网络来完成该任务,那么表达图像的三维张量将会被摊平成一个向量,作为网络的输入,即(width, height, depth)为(4, 4, 1)的图片会被展成维度为16的向量作为网络的输入层。再经过几层不同节点个数的隐藏层,最终输出两个节点,分别表示“有横折的概率”和”没有横折的概率” ,如下图所示。
下面我们用数字(16进制)对图片中的每一个像素点(pixel)进行编号。当使用右侧那种物体位于中间的训练数据来训练网络时,网络就只会对编号为5,6,9,a的节点的权重进行调节。若让该网络识别位于右下角的”横折”时,则无法识别。
解决办法是用大量物体位于不同位置的数据训练,同时增加网络的隐藏层个数从而扩大网络学习这些变体的能力。
前馈神经网络的缺点
然而这样做十分不效率,因为我们知道在左侧的“横折”也好,还是在右侧的”横折”也罢,大家都是”横折”。为什么相同的东西在位置变了之后要重新学习?有没有什么方法可以将中间所学到的规律也运用在其他的位置?换句话说,也就是让不同位置用相同的权重。
卷积神经网络CNN就是让权重在不同位置共享的神经网络。
CNN的局部扫描
在卷积神经网络中,我们先选择一个局部区域,用这个局部区域去扫描整张图片。局部区域所圈起来的所有节点会被连接到下一层的一个节点上。
CNN的输出
深度为复数的情况
现在我们已经知道了depth维度只有1的灰度图是如何处理的。但前文提过,图片的普遍表达方式是下图这样有3个channels的RGB颜色模型。当depth为复数的时候,每个feature detector是如何卷积的?
在输入depth为1时:被filter size为2x2所圈中的4个输入节点连接到1个输出节点上。
在输入depth为3时:被filter size为2x2,但是贯串3个channels后,所圈中的12个输入节点连接到1个输出节点上。
在输入depth为n时: 2x2xn个输入节点连接到1个输出节点上。
CNN(卷积神经网络)
Facebook 将神经网络用于自动标注算法、谷歌将它用于图片搜索、亚马逊将它用于商品推荐、Pinterest 将它用于个性化主页推送、Instagram 将它用于搜索架构。
然而,应用神经网络网络最经典最流行的案例是进行图像处理。在图像处理任务中,使用卷积神经网络进行图像分类。
图像分类是对输入图像的操作,最终输出一组最好地描述了图像内容的分类(如猫、狗等)或分类的概率。对人类来说,识别是打出生便开始学习的技能之一,对成人来说更是信手拈来,毫不费力。我们只需一眼便能快速识别我们所处的环境以及环绕在我们身边的物体。当我们看到一张图片或是环看四周的时候,无需刻意观察,多数时候也能立即描述出场景特征并标记出每一个对象。快速识别不同模式、根据早前知识进行归纳、以及适应不同的图像环境一直都是人类的专属技能,机器尚未享有。
当计算机看到一张图像(输入一张图像)时,它看的是一大堆像素值。根据图片的分辨率和尺寸,它将看到一个 32 x 32 x 3 的数组(3 指代的是 RGB 值)。假设我们有一张 JPG 格式的 480 x 480 大小的彩色图片,那么它对应的数组就有 480 x 480 x 3 个元素。其中每个数字的值从 0 到 255 不等,其描述了对应那一点的像素灰度。当我们人类对图像进行分类时,这些数字毫无用处,可它们却是计算机可获得的唯一输入。其中的思想是:当你提供给计算机这一数组后,它将输出描述该图像属于某一特定分类的概率的数字(比如:80% 是猫、15% 是狗、5% 是鸟)。
我们想要计算机能够区分开所有提供给它的图片,以及搞清楚猫猫狗狗各自的特有特征。这也是我们人类的大脑中不自觉进行着的过程。当我们看到一幅狗的图片时,如果有诸如爪子或四条腿之类的明显特征,我们便能将它归类为狗。同样地,计算机也可以通过寻找诸如边缘和曲线之类的低级特点来分类图片,继而通过一系列卷积层级建构出更为抽象的概念。这是 CNN(卷积神经网络)工作方式的大体概述,
挑一张图像,让它历经一系列卷积层、非线性层、池化(下采样(downsampling))层和完全连接层,最终得到输出。输出可以是最好地描述了图像内容的一个单独分类或一组分类的概率。
卷积层
CNN 的第一层通常是卷积层(Convolutional Layer)。首先需要了解卷积层的输入内容是什么。输入内容为一个 32 x 32 x 3 的像素值数组。现在,解释卷积层的最佳方法是想象有一束手电筒光正从图像的左上角照过。假设手电筒光可以覆盖 5 x 5 的区域,想象一下手电筒光照过输入图像的所有区域。
在机器学习术语中,这束手电筒被叫做过滤器(filter,有时候也被称为神经元(neuron)或核(kernel)),被照过的区域被称为感受野(receptive field)。过滤器同样也是一个数组(其中的数字被称作权重或参数)。重点在于过滤器的深度必须与输入内容的深度相同(这样才能确保可以进行数学运算),因此过滤器大小为 5 x 5 x 3。
现在,以过滤器所处在的第一个位置为例,即图像的左上角。当筛选值在图像上滑动(卷积运算)时,过滤器中的值会与图像中的原始像素值相乘(又称为计算点积)。这些乘积被加在一起(从数学上来说,一共会有 75 个乘积)。现在你得到了一个数字。切记,该数字只是表示过滤器位于图片左上角的情况。我们在输入内容上的每一位置重复该过程。(下一步将是将过滤器右移 1 单元,接着再右移 1 单元,以此类推。)输入内容上的每一特定位置都会产生一个数字。
过滤器滑过所有位置后将得到一个 28 x 28 x 1 的数组,我们称之为激活映射(activation map)或特征映射(feature map)。之所以得到一个 28 x 28 的数组的原因在于,在一张 32 x 32 的输入图像上,5 x 5 的过滤器能够覆盖到 784 个不同的位置。这 784 个位置可映射为一个 28 x 28 的数组。
当我们使用两个而不是一个 5 x 5 x 3 的过滤器时,输出总量将会变成 28 x 28 x 2。采用的过滤器越多,空间维度( spatial dimensions)保留得也就越好。
过滤器
不过,从高层次角度而言卷积是如何工作的?每个过滤器可以被看成是特征标识符( feature identifiers)。这里的特征指的是例如直边缘、原色、曲线之类的东西。想一想所有图像都共有的一些最简单的特征。假设第一组过滤器是 7 x 7 x 3 的曲线检测器。(在这一节,为了易于分析,暂且忽略该过滤器的深度为 3 个单元,只考虑过滤器和图像的顶层层面。)作为曲线过滤器,它将有一个像素结构,在曲线形状旁时会产生更高的数值(切记,我们所讨论的过滤器不过是一组数值!)
回到数学角度来看这一过程。当我们将过滤器置于输入内容的左上角时,它将计算过滤器和这一区域像素值之间的点积。拿一张需要分类的照片为例,将过滤器放在它的左上角。
简单来说,如果输入图像上某个形状看起来很像过滤器表示的曲线,那么所有点积加在一起将会得出一个很大的值!让我们看看移动过滤器时会发生什么。
这个值小了很多!这是因为图像的这一部分和曲线检测器过滤器不存在对应。记住,这个卷积层的输出是一个激活映射(activation map)。因此,在这个带有一个过滤器卷积的例子里(当筛选值为曲线检测器),激活映射将会显示出图像里最像曲线的区域。在该例子中,28 x 28 x 1 的激活映射的左上角的值为 6600。高数值意味着很有可能是输入内容中的曲线激活了过滤器。激活地图右上角的值将会是 0,因为输入内容中没有任何东西能激活过滤器(更简单地说,原始图片中的这一区域没有任何曲线)。
这仅仅是一组检测右弯曲线的过滤器。还有其它检测左弯曲线或直线边缘的过滤器。过滤器越多,激活映射的深度越大,我们对输入内容的了解也就越多。
为了预测出图片内容的分类,网络需要识别更高级的特征,例如手、爪子与耳朵的区别。第一个卷积层的输出将会是一个 28 x 28 x 3 的数组(假设我们采用三个 5 x 5 x 3 的过滤器)。当我们进入另一卷积层时,第一个卷积层的输出便是第二个卷积层的输入。
第一层的输入是原始图像,而第二卷积层的输入正是第一层输出的激活映射。也就是说,这一层的输入大体描绘了低级特征在原始图片中的位置。在此基础上再采用一组过滤器(让它通过第 2 个卷积层),输出将是表示了更高级的特征的激活映射。这类特征可以是半圆(曲线和直线的组合)或四边形(几条直线的组合)。随着进入网络越深和经过更多卷积层后,将得到更为复杂特征的激活映射。
形状的抓取
知道了每个filter在做什么之后,我们再来思考这样的一个filter会抓取到什么样的信息。我们知道不同的形状都可由细小的”零件”组合而成的。
比如下图中,用2x2的范围所形成的16种形状可以组合成格式各样的”更大”形状。卷积的每个filter可以探测特定的形状。又由于Feature Map保持了抓取后的空间结构。若将探测到细小图形的Feature Map作为新的输入再次卷积后,则可以由此探测到”更大”的形状概念。比如下图的第一个“大”形状可由2,3,4,5基础形状拼成。第二个可由2,4,5,6组成。第三个可由6,1组成。
除了基础形状之外,颜色、对比度等概念对画面的识别结果也有影响。卷积层也会根据需要去探测特定的概念。
可以从下面这张图中感受到不同数值的filters所卷积过后的Feature Map可以探测边缘,棱角,模糊,突出等概念。
而filter内的权重矩阵W是网络根据数据学习得到的,也就是说,我们让神经网络自己学习以什么样的方式去观察图片。
拿老妇与少女的那幅图片举例,当标签是少女时,卷积网络就会学习抓取可以成少女的形状、概念。当标签是老妇时,卷积网络就会学习抓取可以成老妇的形状、概念。
多个过滤器
每个过滤器可以抓取探测特定的形状的存在。假如我们要探测下图的长方框形状时,可以用4个过滤器去探测4个基础”零件”
因此我们自然而然的会选择用多个不同的filters对同一个图片进行多次抓取。如下图(动态图过大,如果显示不出,请看到该链接观看) ,同一个图片,经过两个(红色、绿色)不同的filters扫描过后可得到不同特点的Feature Maps,每增加一个filter,就意味着你想让网络多抓取一个特征。
这样卷积层的输出也不再是depth为1的一个平面,而是和输入一样是depth为复数的长方体。
如下图所示,当我们增加一个filter (紫色表示)后,就又可以得到一个Feature Map。将不同filters所卷积得到的Feature Maps按顺序堆叠后,就得到了一个卷积层的最终输出。
这样卷积后输出的长方体可以作为新的输入送入另一个卷积层中处理。
加入非线性
和前馈神经网络一样,经过线性组合和偏移后,会加入非线性增强模型的拟合能力。
将卷积所得的Feature Map经过ReLU变换(elementwise)后所得到的output就如下图所展示。
完全连接层
检测高级特征之后,网络最后的完全连接层就更是锦上添花了。简单地说,这一层处理输入内容(该输入可能是卷积层、ReLU 层或是池化层的输出)后会输出一个 N 维向量,N 是该程序必须选择的分类数量。例如,如果你想得到一个数字分类程序,如果有 10 个数字,N 就等于 10。这个 N 维向量中的每一数字都代表某一特定类别的概率。例如,如果某一数字分类程序的结果矢量是 [0 .1 .1 .75 0 0 0 0 0 .05],则代表该图片有 10% 的概率是 1、10% 的概率是 2、75% 的概率是 3、还有 5% 的概率是 9(注:还有其他表现输出的方式,这里只展示了 softmax 的方法)。
完全连接层观察上一层的输出(其表示了更高级特征的激活映射)并确定这些特征与哪一分类最为吻合。例如,如果该程序预测某一图像的内容为狗,那么激活映射中的高数值便会代表一些爪子或四条腿之类的高级特征。同样地,如果程序测定某一图片的内容为鸟,激活映射中的高数值便会代表诸如翅膀或鸟喙之类的高级特征。大体上来说,完全连接层观察高级特征和哪一分类最为吻合和拥有怎样的特定权重,因此当计算出权重与先前层之间的点积后,你将得到不同分类的正确概率。
步幅和填充
选择了过滤器的尺寸以后,我们还需要选择步幅(stride)和填充(padding)。
步长
步幅控制着过滤器围绕输入内容进行卷积计算的方式。在第一部分我们举的例子中,过滤器通过每次移动一个单元的方式对输入内容进行卷积。过滤器移动的距离就是步幅。在那个例子中,步幅被默认设置为1。步幅的设置通常要确保输出内容是一个整数而非分数。让我们看一个例子。想象一个 7 x 7 的输入图像,一个 3 x 3 过滤器(简单起见不考虑第三个维度),步幅为 1。这是一种惯常的情况。
感受野移动了两个单元,输出内容同样也会减小。注意,如果试图把我们的步幅设置成 3,那我们就会难以调节间距并确保感受野与输入图像匹配。正常情况下,程序员如果想让接受域重叠得更少并且想要更小的空间维度(spatial dimensions)时,他们会增加步幅。
填充
现在让我们看一下填充(padding)。在此之前,想象一个场景:当你把 5 x 5 x 3 的过滤器用在 32 x 32 x 3 的输入上时,会发生什么?输出的大小会是 28 x 28 x 3。注意,这里空间维度减小了。如果我们继续用卷积层,尺寸减小的速度就会超过我们的期望。
在网络的早期层中,我们想要尽可能多地保留原始输入内容的信息,这样我们就能提取出那些低层的特征。比如说我们想要应用同样的卷积层,但又想让输出量维持为 32 x 32 x 3 。为做到这点,我们可以对这个层应用大小为 2 的零填充(zero padding)。零填充在输入内容的边界周围补充零。如果我们用两个零填充,就会得到一个 36 x 36 x 3 的输入卷。
池化层
在几个 ReLU 层之后,程序员也许会选择用一个池化层(pooling layer)。它同时也被叫做下采样(downsampling)层。在这个类别中,也有几种可供选择的层,最受欢迎的就是最大池化( max-pooling)。它基本上采用了一个过滤器(通常是 2x2 的)和一个同样长度的步幅。然后把它应用到输入内容上,输出过滤器卷积计算的每个子区域中的最大数字。
Max pooling的主要功能是downsampling,却不会损坏识别结果。这意味着卷积后的FeatureMap中有对于识别物体不必要的冗余信息。那么我们就反过来思考,这些”冗”信息是如何产生的。
直觉上,我们为了探测到某个特定形状的存在,用一个filer对整个图片进行逐步扫描。但只有出现了该特定形状的区域所卷积获得的输出才是真正有用的,用该filter卷积其他区域得出的数值就可能对该形状是否存在的判定影响较小。
比如下图中,我们还是考虑探测”横折”这个形状。卷积后得到3x3的Feature Map中,真正有用的就是数字为3的那个节点,其余数值对于这个任务而言都是无关的。所以用3x3的Max pooling后,并没有对“横折”的探测产生影响。试想在这里例子中如果不使用Max pooling,而让网络自己去学习。网络也会去学习与Max pooling近似效果的权重。因为是近似效果,增加了更多的parameters的代价,却还不如直接进行Max pooling
池化层还有其他选择,比如平均池化(average pooling)和 L2-norm 池化 。这一层背后的直观推理是:一旦我们知道了原始输入(这里会有一个高激活值)中一个特定的特征,它与其它特征的相对位置就比它的绝对位置更重要。可想而知,这一层大幅减小了输入卷的空间维度(长度和宽度改变了,但深度没变)。
这到达了两个主要目的。第一个是权重参数的数目减少到了75%,因此降低了计算成本。第二是它可以控制过拟合(overfitting)。这个术语是指一个模型与训练样本太过匹配了,以至于用于验证和检测组时无法产生出好的结果。出现过拟合的表现是一个模型在训练集能达到 100% 或 99% 的准确度,而在测试数据上却只有50%。
数据增强技术
如何利用一些简单的转换方法将你现有的数据集变得更大。正如我们之前所提及的,当计算机将图片当作输入时,它将用一个包含一列像素值的数组描述(这幅图)。若是图片左移一个像素。对你和我来说,这种变化是微不可察的。然而对计算机而已,这种变化非常显著:这幅图的类别和标签保持不变,数组却变化了。
这种改变训练数据的数组表征而保持标签不变的方法被称作数据增强技术。这是一种人工扩展数据集的方法。人们经常使用的增强方法包括灰度变化、水平翻转、垂直翻转、随机编组、色值跳变、翻译、旋转等其他多种方法。通过利用这些训练数据的转换方法,你将获得两倍甚至三倍于原数据的训练样本。
FCN(全卷积网络)(Fully Convolutional Network)
分割(语义,实例,全景分割)
分割,顾名思义,就是把一个完整的东西按照某种方式或规则分成若干个部分。
那么什么是图像分割呢?简单来说,就是把图像中属于同一类别或同一个体的东西划分在一起,并将各个子部分区分开来。像下图这样:
为了训练神经网络,图片中这些像素点会按照某种规则被贴上一个“标签”,比如这个像素点是属于人、天空、草地还是树;更详细一点,可以再给它们第二个标签,声明它们是属于“哪一个人”或“哪一棵树”。
对于只有一个标签的(只区分类别)的任务,我们称之为“语义分割”(semantic segmentation);
对于区分相同类别的不同个体的,则称之为实例分割(instance segmentation)。
由于实例分割往往只能分辨可数目标,因此,为了同时实现实例分割与不可数类别的语义分割,2018年Alexander Kirillov等人提出了全景分割(panoptic segmentation)的概念。
下图分别展示了(a)原始图像,(b)语义分割,(c)实例分割和(d)全景分割。
语义分割
图像语义分割(Semantic Segmentation)是图像处理和是机器视觉技术中关于图像理解的重要一环,也是 AI 领域中一个重要的分支。语义分割即是对图像中每一个像素点进行分类,确定每个点的类别(如属于背景、人或车等),从而进行区域划分。目前,语义分割已经被广泛应用于自动驾驶、无人机落点判定等场景中。
截止目前,CNN已经在图像分类分方面取得了巨大的成就,涌现出如VGG和Resnet等网络结构,并在ImageNet中取得了好成绩。CNN的强大之处在于它的多层结构能自动学习特征,并且可以学习到多个层次的特征:
这些抽象特征对物体的大小、位置和方向等敏感性更低,从而有助于分类性能的提高。这些抽象的特征对分类很有帮助,可以很好地判断出一幅图像中包含什么类别的物体。图像分类是图像级别的!
与分类不同的是,语义分割需要判断图像每个像素点的类别,进行精确分割。图像语义分割是像素级别的!但是由于CNN在进行convolution和pooling过程中丢失了图像细节,即feature map size逐渐变小,所以不能很好地指出物体的具体轮廓、指出每个像素具体属于哪个物体,无法做到精确的分割。
针对这个问题,Jonathan Long等人提出了Fully Convolutional Networks(FCN)用于图像语义分割。自从提出后,FCN已经成为语义分割的基本框架,后续算法其实都是在这个框架中改进而来。
FCN与CNN区别
对于一般的分类CNN网络,如VGG和Resnet,都会在网络的最后加入一些全连接层,经过softmax后就可以获得类别概率信息。但是这个概率信息是1维的,即只能标识整个图片的类别,不能标识每个像素点的类别,所以这种全连接方法不适用于图像分割。
而FCN提出可以把后面几个全连接都换成卷积,这样就可以获得一张2维的feature map,后接softmax获得每个像素点的分类信息,从而解决了分割问题,如图4。
反卷积与上采样
上采样(upsampling)一般包括2种方式:
- Resize,如双线性插值直接缩放,类似于图像缩放
- Deconvolution,也叫Transposed Convolution
对于一般卷积,输入蓝色4x4矩阵,卷积核大小3x3。当设置卷积参数pad=0,stride=1时,卷积输出绿色2x2矩阵,如图6。
而对于反卷积,相当于把普通卷积反过来,输入蓝色2x2矩阵(周围填0变成6x6),卷积核大小还是3x3。当设置反卷积参数pad=0,stride=1时输出绿色4x4矩阵,如图7,这相当于完全将图4倒过来
传统的网络是subsampling的,对应的输出尺寸会降低;upsampling的意义在于将小尺寸的高维度feature map恢复回去,以便做pixelwise prediction,获得每个点的分类信息。
上采样在FCN网络中的作用如图8,明显可以看到经过上采样后恢复了较大的pixelwise feature map,这其实相当于一个Encode-Decode的过程。 (编码和解码
FCN的缺陷
- 无法解决实例分割问题
- 速度远不能达到实时
- 不能够应对诸如3D点云等不定型数据
U-Net
U-Net是一种分割网络,能够适应很小的训练集(大约30张图)。
整个U-Net网络结构如图9,类似于一个大大的U字母:首先进行Conv+Pooling下采样;然后Deconv反卷积进行上采样,crop之前的低层feature map,进行融合;然后再次上采样。重复这个过程,直到获得输出388x388x2的feature map,最后经过softmax获得output segment map。总体来说与FCN思路非常类似。
Unet 网络结构是对称的,形似英文字母 U 所以被称为 Unet。整张图都是由蓝/白色框与各种颜色的箭头组成,其中,蓝/白色框表示 feature map;蓝色箭头表示 3x3 卷积,用于特征提取;灰色箭头表示 skip-connection,用于特征融合;红色箭头表示池化 pooling,用于降低维度;绿色箭头表示上采样 upsample,用于恢复维度;青色箭头表示 1x1 卷积,用于输出结果。
U-Net采用了与FCN完全不同的特征融合方式:拼接!
与FCN逐点相加不同,U-Net采用将特征在channel维度拼接在一起,形成更“厚”的特征。所以:
两种特征融合方法
语义分割网络在特征融合时也有2种办法:
- FCN式的逐点相加,
- U-Net式的channel维度拼接融合
运用CNN的分割问题上,主要分为以FCN为基础的结构,和以U-Net为基础的结构。前者的encoder-decoder是非对称的,后者的encoder-decoder是对称的;
U-Net为何适用于医学图像
医学图像特点
- 图像语义较为简单、结构较为固定。我们做脑的,就用脑CT和脑MRI,做胸片的只用胸片CT,做眼底的只用眼底OCT,都是一个固定的器官的成像。由于器官本身结构固定和语义信息没有特别丰富,所以高级语义信息和低级特征都显得很重要(UNet的skip connection和U型结构就派上了用场)。
- 数据量少。医学影像的数据获取相对难一些,很多比赛只提供不到100例数据。所以我们设计的模型不宜过大,如果参数过多,很容易导致过拟合。
- 多模态。相比自然影像,医疗影像比较有趣和不同的一点是,医疗影像是具有多种模态的。以ISLES脑梗竞赛为例,其官方提供了CBF,MTT,CBV,TMAX,CTP等多种模态的数据。这就需要我们更好的设计网络去提取不同模态的特征feature。。
- 可解释性重要。由于医疗影像最终是辅助医生的临床诊断,所以网络告诉医生一个3D的CT有没有病是远远不够的,医生还要进一步的想知道,病灶在哪一层,在哪一层的哪个位置,分割出来了吗,能求体积嘛?同时对于网络给出的分类和分割等结果,医生还想知道为什么,也就是说从医生角度出发,更希望知道医疗AI的可解释性如何
解释医学影像以Attention及CAM(class-activation-map)等可视化方法为主。
因为医学图像边界模糊、梯度复杂,需要较多的高分辨率信息。高分辨率用于精准分割。
人体内部结构相对固定,分割目标在人体图像中的分布很具有规律,语义简单明确,低分辨率信息能够提供这一信息,用于目标物体的识别。
UNet结合了低分辨率信息(提供物体类别识别依据)和高分辨率信息(提供精准分割定位依据),完美适用于医学图像分割。
Seg-Net
解码器
分割任务中的编码器encode与解码器decode就像是玩“你来比划我来猜”的双方:比划的人想把看到的东西用一种方式描述出来,猜的人根据比划的人提供的信息猜出答案。
其中,“比划的人”叫做编码器,“猜的人”就是解码器。
具体来说,编码器的任务是在给定输入图像后,通过神经网络学习得到输入图像的特征图谱;而解码器则在编码器提供特征图后,逐步实现每个像素的类别标注,也就是分割。
通常,分割任务中的编码器结构比较类似,大多来源于用于分类任务的网络结构,比如VGG。这样做有一个好处,就是可以借用在大数据库下训练得到的分类网络的权重参数,通过迁移学习实现更好的效果。因此,解码器的不同在很大程度上决定了一个基于编解码结构的分割网络的效果。
SegNet的编码器结构与解码器结构是一一对应的,即一个decoder具有与其对应的encoder相同的空间尺寸和通道数。对于基础SegNet结构,二者各有13个卷积层,其中编码器的卷积层就对应了VGG16网络结构中的前13个卷积层。
下图是SegNet的网络结构,其中蓝色代表卷积+Batch Normalization+ReLU,绿色代表max-pooling,红色代表上采样,黄色是Softmax。
SegNet与FCN的对应结构相比,体量要小很多。这主要得益于SegNet中为了权衡计算量而采取的操作:用记录的池化过程的位置信息替代直接的反卷积操作。具体如下图所示。
Seg-Net与FCN解码方式的不同
图中左侧是SegNet使用的解码方式,右侧是FCN对应的解码方式。可以看到,SegNet的做法是先根据位置信息生成稀疏的特征图,再利用后续的卷积计算恢复稠密特征图。而FCN则直接利用反卷积操作求得上采样后的特征图,再将其与编码器特征图相加。
改变解码器的参数
前文已经提到,编解码结构中,解码器的效果和复杂程度对于整个分割网络的影响是非常大的。这里我们就一起来看一下不同解码器结构和它们的效果。
SegNet中一共尝试了8种不同的解码结构,先上结果:
这些变体共用相同的编码器结构,只是在解码器结构上有所不同。比如,将解码器的结构单纯减少层数,改变解码器最后一层通道数,改变编解码器对应结构之间的连接方式(只连接池化信息、保留特征层内信息或全部保留),改变采样方式等。
除上面几种变体外,论文中还尝试了改变上采样方法,或取消池化和下采样过程,但是这些改变都没有带来更好的结果。
解码器总结
- 保留编码器所有特征图所实现的效果最好,在这一点上语义分割边缘轮廓描述度量(BF)体现最为明显。
- 当推理过程的内存受限时,可以使用编码器特征图的压缩形式(比如缩小维度、使用池化信息等),但需要搭配合适的解码器形式(比如SegNet类型的)来提升表现。
- 在给定编码器时,越大的解码器效果越好。
图像处理的非深度学习方法
图像分割是什么?如果下学术定义,就是把图像分割成想要的语义上相同的若干子区域,看上面的自动驾驶的分割任务,路是路,车是车,树是树。
这些子区域,组成图像的完备子集,相互之间不重叠。图像分割可以被看作是一个逐像素的图像分类问题
没有深度学习的那些年,也发展出了非常多的图像分割技术。
边缘与阈值法
简单的边缘检测也曾被用于图像分割,但是因为要做复杂后处理以及后面和其他方法有重叠,这里就不再说了,而是从阈值法开始说。
阈值法的基本思想是基于图像的灰度特征来计算一个或多个灰度阈值,并将图像中每个像素的灰度值与阈值相比较。
其中,最广泛使用也最具有代表性质就是OTSU【1】方法,它是用于灰度图像分割的方法,核心思想就是使类间方差最大。
这样的方法,非常简单,要求被分割的物体颜色纹理比较紧凑,类内方差小,只适合一些文本图像的处理,比如车牌,比如指纹。
区域增长,分裂
阈值法的一个硬伤是太粗暴简单,哪怕是自适应的局部阈值法,一样难逃无法分割类内方差较大的目标的宿命。它完全没有利用好像素的空间信息,导致分割结果极其容易受噪声干扰,经常出现断裂的边缘,需要后处理。
所以,区域生长法出现了,它通过一些种子点,再加上相似性准则来不断扩充区域直到达到类别的边界,这时候分割结果是连续的了。
区域分裂则是反过程,不再详述。区域增长法的佼佼者,就是分水岭算法【2】。
分水岭算法是一种基于拓扑理论的数学形态学的分割方法,将图像中每一点像素的灰度值表示该点的海拔高度,每一个局部极小值称为集水盆,而集水盆的边界则是分水岭。分水岭算法有很多种实现算法,常用浸水模拟法。
分水岭算法对于弱边缘有不错的响应,因此常被用于材料图像的分割,以及产生超像素用于提高其他方法的分割效率。咱在硕士期间也与师姐鼓捣过半导体材料的分割,还不错。
说到这里,超像素也是很重要的一种方法,某种程度上也能被归为图像分割的方法。SLIC,Meanshift等都是非常经典的方法,去文【3】中做更详细解读吧。
图割
以graphcut【4】为代表的图割方法,是传统图像分割里面鲁棒性最好的方法,它是一种概率无向图模型(Probabilistic undirected graphical model),又被称Markov random field马尔可夫随机场。
Graphcut的基本思路,就是建立一张图,看下面这张图,其中以图像像素或者超像素作为图像顶点,然后优化的目标就是要找到一个切割,使得各个子图不相连从而实现分割,前提是移除边的和权重最小。
后来图割方法从MRF发展到CRF,也就是条件随机场。它通常包含两个优化目标,一个是区域的相似度,被称为区域能量项,即piecewise能量。一个是被切断边的相似度,被称为边缘能量项,即pairwise能量。它追求区域能量项的最大化以及边缘能量的最小化,也就是区域内部越相似越好,区域间相似度越低越好。
图割方法很通用,对于纹理比较复杂的图像分割效果也不错。缺点是时间复杂度和空间复杂度较高,所以通常使用超像素进行加速计算,上面的分水岭算法就可以拿来用用。
graphcut的迭代版本,也就是grabcut【5】更好用,它的基本思路是;使用混合高斯**模型(Gaussian Mixture Model,GMM)**替代了graphcut基于灰度的模型,初始的混合高斯模型的构建,通过用户交互来指定,只需要指定确定性的背景像素区域即可,通常是画一个框。
多年以后再看下面这张图,效果依然是惊艳的,边缘很不错。不像上面的几个方法,图割方法仍然被广泛使用,deeplab系列的前几篇文章就用到了全连接的crf,它与mrf的区别可以参考这篇文章【Discriminative fields for modeling spatial dependencies in natural images】。
轮廓模型
轮廓模型大部分人可能不知道,它的基本思想是使用连续曲线来表达目标轮廓,并定义一个能量泛函,其自变量为曲线,将分割过程转变为求解能量泛函的最小值的过程。数值实现可通过求解函数对应的欧拉(Euler-Lagrange)方程来实现。包括以snake模型为代表的参数活动轮廓模型和以水平集方法为代表的几何活动轮廓模型。
当能量达到最小时的,曲线位置就处于正确的目标轮廓。
该类分割方法具有几个显著的特点:(1)由于能量泛函是在连续状态下实现,所以最终得到的图像轮廓可以达到较高的精度;(2)通过约束目标轮廓为光滑,同时融入其它关于目标形状的先验信息,算法可以具有较强的鲁棒性;(3)使用光滑的闭合曲线表示物体的轮廓,可获取完整的轮廓,从而避免传统图像分割方法中的预/后处理过程。
不过,缺点也很明显,比较敏感,容易陷入局部极值。
下面是我的硕士论文【6】中采用水平集方法分割出的肿瘤,就是白色那一块。这个方法的数学味有点浓,考虑到咱们是闲聊,就不摆公式了,毕竟后面还有很多事。