image segmentation

大多数人接触“语义”都是在和文字相关的领域,或语音识别,期望机器能够识别你发出去的消息或简短的语音,然后给予你适当的反馈和回复。嗯,看到这里你应该已经猜到了,图像领域也是存在“语义”的。

今天是AI大热年,很多人都关注与机器人的语音交互,可是有没有想过,将来的机器人如果不能通过图像来识别主人,家里的物品、宠物,那该多没意思。说近一些,假如扫地机器人能够机智地绕开你丢在地上的臭袜子而扫走旁边的纸屑,一定能为你的生活解决不少麻烦。

没错,图像语义分割是AI领域中一个重要的分支,是机器视觉技术中关于图像理解的重要一环,是不是听上去即重要又牛X闪闪的。

近年的自动驾驶技术中,也需要用到这种技术。车载摄像头探查到图像,后台计算机可以自动将图像分割归类,以避让行人和车辆等障碍。



图像语义分割的意思就是机器自动分割并识别出图像中的内容,比如给出一个人骑摩托车的照片,机器判断后应当能够生成右侧图,红色标注为人,绿色是车(黑色表示back ground)。

所以图像分割对图像理解的意义,就好比读古书首先要断句一样。

在Deeplearning技术快速发展之前,就已经有了很多做图像分割的技术,其中比较著名的是一种叫做“Normalized cut”的图划分方法,简称“N-cut”。

N-cut的计算有一些连接权重的公式,这里就不提了,它的思想主要是通过像素和像素之间的关系权重来综合考虑,根据给出的阈值,将图像一分为二。

下图是将像素间的关系信息简单描述成为距离,根据距离差距来划分图像的示例:

在实际运用中,每运行一次N-cut,只能切割一次图片,为了分割出图像上的多个物体,需要多次运行,下图示例了对原图a进行7次N-cut后,每次分割出的结果。

但是可以很明显的看到这种简单粗暴的分割方式并不准确,趴在地上的运动员肢体在b图中分割出来,而他的手臂则在h图中被分割,显然是错误的。

N-cut技术的缺陷很明显,于是有了一种更新的优化方式,这种优化方式为了避免机器不能很好的分割类似上面例子中“衣服和肢体颜色反查太大导致分割错误”的情况,增加了人机交互,在分割过程中,需要人工干预参与完成。

这种需要人机交互的技术叫Grab Cut

[敲黑板]~~ 注意,PS里就使用了这种技术。

这种技术其实是这样的,给定一张图片,然后人工在想要抠图(也就是我们说的分割)的区域画一个红框,然后机器会对略小于这个框的内容进行“主体计算”,嗯,这个“主体计算”是我起的名字,为了你们更好的理解背后复杂的设计和公式,因为机器会默认红框中部是用户期望得到的结果,所以将中部作为主体参考,然后剔除和主体差异较大的部分,留下结果。

此技术中,抠出来的部分叫“前景”,剔除的部分叫“背景”。

有时候还挺好用的,但是稍微复杂一点的时候问题就来了:比如要抠下面这个戴头盔的大兵,头盔颜色和背后岩石颜色很相近,结果机器就会把头盔部分剔除,同样脖子附近的山岩也被当做了前景而保留了进来。

此时又需要进行人工干预了,需要手动在图像上进行标注,画白色线表示是希望保留的前景,红色表示背景,指导辅助机器进行判断,再次运算后,得到了较好的期望结果。

虽然看上去Grab Cut给出的结果还不错,但缺点也很明显,首先,它同N-cut一样也只能做二类语义分割,说人话就是一次只能分割一类,非黑即白,多个目标图像就要多次运算。其次,它需要人工干预,这个弱点在将来批量化处理和智能时代简直就是死穴

OK,人类的智慧是无止境的,DeepLearning(深度学习)终于开始大行其道了。

深度学习是机器学习的一个分支,主要指深度神经网络算法,深度神经网络比普通神经网络层次更多,能够更好地捕捉数据中的深层次关系,得到的模型较为准确,主要用来进行特征学习。

先别急着晕,我们先来看看神经网络是怎么工作的。

神经网络是模仿人的神经元而建立的人工神经元系统,多输入单输出,同时输出又作为下一个神经元的输入……(请自行脑补那张牙舞爪妖孽的神经元细胞~什么?没见过?文科生,拖出去~~)

下图表示的是一个单个神经元:

把这些单个神经元组织在一起,便形成了神经网络。下图便是一个三层神经网络结构:

上图中最左边的原始输入信息称之为输入层,最右边的神经元称之为输出层(上图中输出层只有一个神经元),中间的叫隐藏层

深度神经网络系统中的层数比较多,达到8-10层(普通神经网络的层数通常3-4层)。

在此前使用的图像识别算法中,主流的技术是卷积神经网络算法(Convolutional Neural Networks),简称CNN卷积神经网络就是一种深度神经网络

但是在2015年的CVPR上发表了一篇很牛X的论文(路人甲:请问CVPR是神马?答:CVPR可以简单理解为这个领域的最重量级的会议:国际计算机视觉与模式识别会议),提出了FCN即 全卷积神经网络(Fully Convolutional Networks)。

为什么说这个FCN论文很牛叉呢?看起来只是多了一个字而已呀,有什么不得了的呢?

嗯,不得不说,真是“差之毫厘,谬以千里”啊。

我还是先来帮大家复习一下卷积。

我查了很多书,卷积有各种各样的公式,还有各种各样的推导算法,但是为了降低本文的难读指数,所以我直接跳到卷积的物理意义,不要太care那些公式,其实卷积的物理意义,就是“加权叠加”。

在对图像处理进行卷积时,根据卷积核的大小,输入和输出之间也会有规模上的差异。

来看一张动图(仅做示例)

上图左边5*5的方块视为图像输入,黄色移动的3*3以及里面的数字(*1/*0)是卷积核,该卷积核按照步长为1的顺序依次从原始输入的左上角一直移动计算叠加到右下角,卷积核一共移动9次。

九次的位置对应到右侧的3*3的相应格内,格中的数字便是卷积值,(此处是卷积核所覆盖的面积内元素相乘再累加的结果)。

9次移动计算完毕后,右侧3*3的新矩阵为此次卷积层的计算结果。

如果这么说还是不太好理解,没关系,我有更直观的办法^_^。

在实际计算过程中,输入是一张原始图片和滤波器filter(一组固定的权重,也就是上面我们说的卷积核对应的实际意义)做内积后得到新的二维数据。

不同的滤波器filter会得到不同的输出数据,比如轮廓、颜色深浅,如果想提取图像的不同特征,需要用不同的滤波器filter提取想要的关于图像的特定信息。

上图为一个卷积层中的卷积处理过程,注意上下两次卷积核内容是不同的,所以得到两种处理结果。

等号右边的新的二维信息在CNN网络中,会作为下一个卷积层的输入,即在下一个卷积层计算时,右边的图像会作为输入的原始图像。

在CNN网络中,一共会进行5次卷积层计算。

路人甲:那最后会得到一个什么鬼?

沈MM:咳咳,在连续的5个卷积层计算后,紧跟这的是3个全连接层。

路人甲:什么是全连接层?

沈MM:全连接层,并不是一个二维图像,而是—— 一个一维向量

路人甲已哭晕在厕所。

这三个一维向量的前两个向量长度是4096,最后一个向量长度是1000.

为什么是1000?

因为在CNN网络中,有1000个分类,最后的这个向量中的1000个元素表达的信息是:这张原始输入图片中的东西可能是这1000个分类中的物体的概率。

是的,一张图,算了半天,最后给出的是,这张图是个什么玩意的答案。

右侧绿色箭头指向的表示最后一个全连接层的向量中,表示各种物体的概率,上图被识别为一辆车。

好了,上面说的是卷积神经网络CNN的处理过程(相信我我已经很简化了)。

那么全卷积神经网络呢?

大家应该注意到,CNN的输入是图像,输出是一个结果,或者说是一个值,一个概率值。

FCN提出所追求的是,输入是一张图片是,输出也是一张图片,学习像素到像素的映射

上图上半部分是CNN网络,下半部分是CN网络

那么“全卷积”又体现在哪里呢?

CNN网络中的后三层,都是一维的向量,计算方式不再采用卷积,所以丢失了二维信息,而FCN网络中,将这三层全部转化为1*1的卷积核所对应等同向量长度的多通道卷积层,使后三层也全部采用卷积计算,整个模型中,全部都是卷积层,没有向量,所以称为“全卷积”。

FCN将第6层和7层分别从4096长度的向量转化为4096通道的卷积层,第8层则是21通道的卷积层。之所以第8层从1000缩减到21,是因为FCN使用的识别库是PASCAL VOC,在PASCAL VOC中有20种物体分类,另外一个background分类。(关于PASCAL VOC参见附录)

再多说一句,以下(甚至全文)所用到的分割图片中不同的颜色就表示不同的物体类别,一共有21种颜色:

CNN的识别是图像级的识别,也就是从图像到结果,而FCN的识别是像素级的识别,对输入图像的每一个像素在输出上都有对应的判断标注,标明这个像素最可能是属于一个什么物体/类别。

在此处特别要指出的是,在实际的图像语义分割测试时,输入是一个H*W*3的三通道彩色图像,而输出是一个H*W的矩阵。

这就可以简单看做每一个像素所携带的信息是多维的,比如颜色,就分为3层,分别对应R、G、B三个值。(不知道什么是RGB的,鉴定为文科生,请迅速撤离,谢谢)

所以在进行卷积的时候,每一个通道都是要独立计算的,计算完之后再叠加,得到最终卷积层结果。

如果卷积核移动的步长为1,那么卷积是按照像素排列去挨个计算的,计算量可想而知会有多么庞大。但是在实际中,相邻的像素往往都是一类,按照像素依次计算就显得冗余,所以在卷积之后会对输出进行一次池化(pooling)处理

那么什么又是池化呢?

来,我们再来看一张动图:

池化简单来说就是将输入图像切块,大部分时候我们选择不重叠的区域,假如池化的分割块大小为 h*h,分割的步长为 j,那么一般 h=j,就像上图,如果需要重叠,只需要 h>j 即可。

对完整图像切分,再取切分区域中所有值的均值或最大值作为代表该区域的新值,放入池化后的二维信息图中。得到的新图就是池化结果。

在CNN和FCN的网络模型中,每一个卷积层,都包含了[卷积 池化]处理,这就是传说中的“下采样”,但这样处理之后的结果是:图像的像素信息变小了,每一层的像素信息都是前一层的1/2大小,到第五层的时候,图像大小为原始图像的1/32

在CNN算法里,这并没有什么要紧的,因为CNN最终只输出一个结果:“这个图上是个啥”,但是FCN不同,FCN是像素级别的识别,也就是输入有多少像素,输出就要多少像素,像素之间完全映射,并且在输出图像上有信息标注,指明每一个像素可能是什么物体/类别。

所以就必须对这1/32的图像进行还原

这里用到个纯数学技术,叫“反卷积”,对第5层进行反卷积,可以将图像扩充至原来的大小(严格说是近似原始大小,一般会大一点,但是会裁剪掉,为什么会大的原理略复杂,这里先不提,以后写进阶版再放进来)。

——这个“反卷积”称为“上采样”。(和下采样对应)

在技术上,我们可以对任一层卷积层做反卷积处理,得到最后的图像,比如用第三层(8s-8倍放大),第四层(16s-16倍放大),第五层(32s-32倍放大)得到的分割结果。

来看一张各层还原后的对比图,分别是:

通过对比可以很明显看到:在16倍还原和8倍还原时,能够看到更好的细节,32倍还原出来的图,在边缘分割和识别上,虽然大致的意思都出来了,但细节部分(边缘)真的很粗糙,甚至无法看出物体形状。

为什么会这样呢?

这里就涉及到一个感受域(receptive field)的概念。较浅的卷积层(靠前的)的感受域比较小,学习感知细节部分的能力强,较深的隐藏层(靠后的),感受域相对较大,适合学习较为整体的、相对更宏观一些的特征。

所以在较深的卷积层上进行反卷积还原,自然会丢失很多细节特征。

于是我们会在反卷积步骤时,考虑采用一部分较浅层的反卷积信息辅助叠加,更好的优化分割结果的精度:

尽管FCN的提出是一条很牛叉的路,但还是无法避免有很多问题,比如,精度问题,对细节不敏感,以及像素与像素之间的关系,忽略空间的一致性等问题。

于是更牛的大牛就出现了。

有牛人提出一种新的卷积计算方式,开始称为“带hole”的卷积,也就是使用一种“疏松的卷积核”来计算,以此来取代池化的处理。

上面已经讲过,池化操作能够减少计算量,同时也能防止计算结果过拟合,那么单纯取消池化操作又会使单层网络的感受域缩小,但如果使用“疏松的卷积核”来处理卷积,可以达到在不增加计算量的情况下增加感受域,弥补不进行池化处理后的精度问题。

括弧:这种带洞的卷积方式后来起了一个高雅的名字叫做:“Dilated Convolutions”。

这种方式人为加大了卷积核内部元素之间的距离,可参考下图:

红点表示卷积核的元素,绿色表示感受域,黑线框表示输入图像。

a为原始卷积核计算时覆盖的感受域,b为当卷积核覆盖的元素间距离增大的情况,不再在连续的空间内去做卷积,跳着做,当这个距离增加的越大时,单次计算覆盖的感受域面积越大。

上图不太好理解的话再来看一张图:(个人觉得下面这个图非常好理解)

上层绿色点表示输入层像素点,下层黄色是输出层(单次计算时的层级关系),当卷积核元素间距为0时(相邻),123对应输出A,234对应输出B,345对应输出C,那么输出ABC三个元素结果的感受域只覆盖了12345这几个原始像素点。

如果采用稀疏的卷积核,假设间距为1(相当于卷积计算时跳一个像素再取值计算),如图示,那么结果A对应的输入是135,结果B对应的输入是246,结果C对应的输入是357,同样输出ABC三个结果,在原始图像上取的像素点的长度就多了。

这是水平X轴方向上的扩展,在Y轴上也会有同样的扩展,感受域在没有增加计算(相对于池化操作后)的情况下增大了,并且保留了足够多的细节信息,对图像还原后的精度有明显的提升。

看一下对比图:

第一列是原始图像,最后一列是手工标注的训练输入图像,第二列为FCN在1/8倍数下的还原,第三列则是采用了新的卷积算法的还原图像,可以很明显看到,第三列对细节的分割明显优于第二列FCN 8倍的图像。

刚才还提到了第二个问题,即像素与像素之间的逻辑关系的问题,毕竟前面再牛叉的算法也只是单纯的计算没有根据物理意义进行判断在输出的标注里这些结果是否合法(符合现实逻辑)。

很多以深度学习为框架的图像语义分割系统都使用了一种叫做“条件随机场”( Conditional Random Field,简称CRF)的技术作为输出结果的优化后处理手段。其实类似技术种类较多,比如还有马尔科夫随机场(MRF)和高斯条件随机场(G-CRF)用的也比较多,但原理都较为类似。

简单来介绍一下“条件随机场”的概念。

FCN是像素到像素的影射,所以最终输出的图片上每一个像素都是标注了分类的,将这些分类简单地看成是不同的变量,每个像素都和其他像素之间建立一种连接,连接就是相互间的关系。

于是就会得到一个“完全图”:

上图是以4*6大小的图像像素阵列表示的简易版。

那么在全链接的 CRF 模型中,有一个对应的能量函数:

嗯,不要问我这个公式里各种符号是啥,我看不懂。但是我知道这个公式是干嘛滴:

其中等号右边第一个一元项,表示像素对应的语义类别,其类别可以由FCN或者其他语义分割模型的预测结果得到;而第二项为二元项,二元项可将像素之间的语义联系/关系考虑进去。

这么说太抽象,举个简单的例子,“天空”和“鸟”这样的像素在物理空间是相邻的概率,应该要比“天空”和“鱼”这样像素相邻的概率大,那么天空的边缘就更应该判断为鸟而不是鱼(从概率的角度)。

通过对这个能量函数优化求解,把明显不符合事实识别判断剔除,替换成合理的解释,得到对FCN的图像语义预测结果的优化,生成最终的语义分割结果。

优化后的对比图:

上图第二列是FCN网络8倍还原分割结果,第三列是将CRF植入FCN处理后的结果。

可以很明显的看到,第三列的物体识别无论是轮廓细节分割还是物体识别,都优于第二列,特别是第二行的沙发中有奇怪的红色东西的识别,在进行CRF优化之后,还原成了绿色的沙发。

OK,说了这么多,终于快要讲完了(好累)。

以上就是目前较为前沿的图像语义分割技术。

目前的这种机器学习方式还属于监督性学习,牛叉闪闪的科学家们还是希望将来可以实现半监督弱监督式学习,这样更类似人类的学习认知方式。

在这条道路上,还有很多有趣的东西,比如示例级别(instance level)的图像语义分割问题也同样热门。

该类问题不仅需要对不同语义物体进行图像分割,同时还要求对同一语义的不同个体进行分割(例如需要对图中出现的九把椅子的像素用不同颜色分别标示出来)。

时间: 2024-10-14 11:01:51

image segmentation的相关文章

论文阅读笔记:Fully Convolutional Networks for Semantic Segmentation

这是CVPR 2015拿到best paper候选的论文. 论文下载地址:Fully Convolutional Networks for Semantic Segmentation 尊重原创,转载请注明:http://blog.csdn.net/tangwei2014 1.概览&主要贡献 提出了一种end-to-end的做semantic segmentation的方法,简称FCN. 如下图所示,直接拿segmentation 的 ground truth作为监督信息,训练一个端到端的网络,让

(转)Image Segmentation with Tensorflow using CNNs and Conditional Random Fields

Daniil's blog Machine Learning and Computer Vision artisan. About/ Blog/ Image Segmentation with Tensorflow using CNNs and Conditional Random Fields Tensorflow and TF-Slim | Dec 18, 2016 A post showing how to perform Image Segmentation with a recentl

arpa/inet.h所引起的Segmentation fault及网络编程常见的头文件

最近在学习Linux网络编程方面的知识,感觉还是有些困难.主要是对协议过程的理解,还有socket的API的理解不够深刻.今天复习编写了一个TCP的服务端和客户端的程序实现client.c从命令行参数中获得一个字符串发给服务器,然后接收服务器返回的已处理的字符串并打印. server.c 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <unistd.h>

论文笔记《Feedforward semantic segmentation with zoom-out features》

<Feedforward semantic segmentation with zoom-out features>,CVPR 2015 这篇文章的方法是superpixel-level的,主要是基于CNN实现,是fully supervised. 首先对输入图像以superpixel为单位提取CNN特征(使用VGG16),然后把这些特征作为CNN classifier(使用imageNet)的输入,imageNet输出是每个superpixel的class. 这篇文章的亮点应该是:1,它把C

函数栈溢出引起的段错误segmentation fault

遇到了一个奇怪的问题: 有一个回调函数中发生了段错误,但经检查也没有什么明显的错误,然后用排除法一点一点屏蔽,最后定位在一个函数里出错,但这个函数没什么明显错误.最后把入口参数改为引用传递就不报错误. 但隔了一段时间这个函数又报错了,原因是我加一行代码,但这行代码就是一个赋值语句:于是我不甘心,又开始排除法,最后定位到一个变量,加上它报错,不加就不报错:我一直怀疑是不是linux对一个函数的大小有限制:于是将这个函数换成全局变量,而在此函数中用的此变量时候采用指针,诶,不再报段错误了,世界终于安

Segmentation Fault的一种定位方法

1. 介绍 网上有很多Segmentation Fault的调试方法,下面这篇文件就很好 <Linux环境下段错误的产生原因及调试方法小结> 然而笔者在实际的使用中由于各种原因总觉得不够用 于是在网上找到了一种个人觉得更直接的方法 2. 原理 Segmentation Fault发生的时候,程序收到了信号11(SIGSEGV) 我们捕获该信号,然后利用事故发生时保存的寄存器现场加上栈信息定位到具体行 这里参考了< C/C++捕获段错误,打印出错的具体位置(精确到哪一行) > 使用其

结构体指针之 段错误 具体解释(segmentation fault)

一个网友问了我一个问题.一个C程序执行出现了段错误,这个问题非常好.非常多刚開始学习的人都easy犯这个错误,详细代码例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > 这个编译没有问题,可是执行是段错误    Segmentation fault 由于你定义了一个结构体指针p.用来指向此类

app打包时报错unable to execute command: Segmentation fault: 11

问题:打包时报错   clang: error:unable to execute command: Segmentation fault: 11 clang: error:linker command failed due to signal (use -v to see invocation) app在上架的时候遇到这个报错问题,一开始以为是证书或者是配置描述文件哪里出错了.作为新手,在试了好多方法依然无法解决之后,只能无奈按照app上架流程又完完全全的重新过了一遍,在点击Archive后的

记一次PHP“Segmentation fault”调试经历

遇到的问题: 在linux上安装php5.5.26.phalcon2.0扩展.xhprof扩展,均正常安装,并可单独运行.但放在一起运行时出现“Segmentation fault”错误.注:xhprof是从github上下载的最新版. 遇到问题时的上下文: 1: 新建项目,使用phalcon命令行工具 phalcon create-project store 2:修改入口文件,加入xhprof支持 3:web访问出现502,无任何php级别的错误日志 在终端下执行:php index.php

strcat函数造成的段错误(Segmentation fault)

转自:http://book.51cto.com/art/201311/419441.htm 3.21  strcat函数造成的段错误 代码示例 int main() { char dest[7]="12345"; char* src = "abcdefghigklmnopqrstuvwxyz"; strcat(dest, src); cout << "dest:" << dest << endl; retur