技术标签: 语义分割 计算机视觉 Datawhale学习打卡 pytorch
语义分割(全像素语义分割)作为经典的计算机视觉任务(图像分类,物体识别检测,语义分割)。其结合了图像分类、目标检测和图像分割,通过一定的方法将图像分割成具有一定语义含义的区域块,并识别出每个区域块的语义类别,实现从底层到高层的语义推理过程,最终得到一幅具有逐像素语义标注的分割图像。
FCN原理及网络结构
FCN首先将一幅RGB图像输入到卷积神经网络后,经过多次卷积以及池化过程得到一系列的特征图,然后利用反卷积层对最后一个卷积层得到的特征图进行上采样,使得上采样后特征图与原图像的大小一样,从而实现对特征图上的每个像素值进行预测的同时保留其在原图像中的空间位置信息,最后对上采样特征图进行逐像素分类,逐个像素计算softmax分类损失。
主要特点:
普通的池化会缩小图片的尺寸,比如VGG16经过5次池化后图片被缩小了32倍。为了得到和原图等大小的分割图,我们需要上采样、反卷积。
反卷积和卷积类似,都是相乘相加的运算。只不过后者是多对一,前者是一对多。而反卷积的前向和反向传播,只用颠倒卷积的前后向传播即可。如下图所示:
跳跃结构
经过全卷积后的结果进行反卷积,基本上就能实现语义分割了,但是得到的结果通常是比较粗糙的。
如上图所示,对原图像进行卷积conv1、pool1后原图像缩小为1/2;之后对图像进行第二次conv2、pool2后图像缩小为1/4;接着继续对图像进行第三次卷积操作conv3、pool3缩小为原图像的1/8,此时保留pool3的featureMap;接着继续对图像进行第四次卷积操作conv4、pool4,缩小为原图像的1/16,保留pool4的featureMap;最后对图像进行第五次卷积操作conv5、pool5,缩小为原图像的1/32,然后把原来CNN操作中的全连接变成卷积操作conv6、conv7,图像的featureMap数量改变但是图像大小依然为原图的1/32,此时图像不再叫featureMap而是叫heatMap。
现在我们有1/32尺寸的heatMap,1/16尺寸的featureMap和1/8尺寸的featureMap,1/32尺寸的heatMap进行upsampling操作之后,因为这样的操作还原的图片仅仅是conv5中的卷积核中的特征,限于精度问题不能够很好地还原图像当中的特征。因此在这里向前迭代,把conv4中的卷积核对上一次upsampling之后的图进行反卷积补充细节(相当于一个插值过程),最后把conv3中的卷积核对刚才upsampling之后的图像进行再次反卷积补充细节,最后就完成了整个图像的还原。
具体来说,就是将不同池化层的结果进行上采样,然后结合这些结果来优化输出,分为FCN-32s,FCN-16s,FCN-8s三种,第一行对应FCN-32s,第二行对应FCN-16s,第三行对应FCN-8s。 具体结构如下:
图中,image是原图像,conv1,conv2…,conv5为卷积操作,pool1,pool2,…pool5为pool操作(pool就是使得图片变为原图的1/2),注意con6-7是最后的卷积层,最右边一列是upsample后的end to end结果。必须说明的是图中nx是指对应的特征图上采样n倍(即变大n倍),并不是指有n个特征图,如32x upsampled 中的32x是图像只变大32倍,不是有32个上采样图像,又如2x conv7是指conv7的特征图变大2倍。
(1)FCN-32s过程
只需要留意第一行,网络里面有5个pool,所以conv7的特征图是原始图像1/32,可以发现最左边image的是32x32(假设以倍数计),同时我们知道在FCN中的卷积是不会改变图像大小(或者只有少量像素的减少,特征图大小基本不会小很多)。看到pool1是16x16,pool2是8x8,pool3是4x4,pool4是2x2,pool5是1x1,所以conv7对应特征图大小为1x1,然后再经过32x upsampled prediction 图片变回32x32。FCN作者在这里增加一个卷积层,卷积后的大小为输入图像的32(2^5)倍,我们简单假设这个卷积核大小也为32,这样就是需要通过反馈训练32x32个权重变量即可让图像实现end to end,完成了一个32s的upsample。FCN作者称做后卷积,他也提及可以称为反卷积。事实上在源码中卷积核的大小为64,同时没有偏置bias。还有一点就是FCN论文中最后结果都是21×*,这里的21是指FCN使用的数据集分类,总共有21类。
(2)FCN-16s过程
现在我们把1,2两行一起看,忽略32x upsampled prediction,说明FCN-16s的upsample过程。FCN作者在conv7先进行一个2x conv7操作,其实这里也只是增加1个卷积层,这次卷积后特征图的大小为conv7的2倍,可以从pool5与2x conv7中看出来。此时2x conv7与pool4的大小是一样的,FCN作者提出对pool4与2x conv7进行一个fuse操作(事实上就是将pool4与2x conv7相加,另一篇博客说是拼接,个人认为是拼接)。fuse结果进行16x upsampled prediction,与FCN-32s一样,也是增加一个卷积层,卷积后的大小为输入图像的16(2^4)倍。我们知道pool4的大小是2x2,放大16倍,就是32x32,这样最后图像大小也变为原来的大小,至此完成了一个16s的upsample。现在我们可以知道,FCN中的upsample实际是通过增加卷积层,通过bp反馈的训练方法训练卷积层达到end to end,这时卷积层的作用可以看作是pool的逆过程。
3)FCN-8s过程
这是我们看第1行与第3行,忽略32x upsampled prediction。conv7经过一次4x upsample,即使用一个卷积层,特征图输出大小为conv7的4倍,所得4x conv7的大小为4x4。然后pool4需要一次2x upsample,变成2x pool4,大小也为4x4。再把4x conv7,2x pool4与pool3进行fuse,得到求和后的特征图。最后增加一个卷积层,使得输出图片大小为pool3的8倍,也就是8x upsampled prediction的过程,得到一个end to end的图像。实验表明FCN-8s优于FCN-16s,FCN-32s。 我们可以发现,如果继续仿照FCN作者的步骤,我们可以对pool2,pool1实现同样的方法,可以有FCN-4s,FCN-2s,最后得到end to end的输出。这里作者给出了明确的结论,超过FCN-8s之后,结果并不能继续优化。
结合上述的FCN的全卷积与upsample,在upsample最后加上softmax,就可以对不同类别的大小概率进行估计,实现end to end。最后输出的图是一个概率估计,对应像素点的值越大,其像素为该类的结果也越大。FCN的核心贡献在于提出使用卷积层通过学习让图片实现end to end分类。
事实上,FCN有一些短处,例如使用了较浅层的特征,因为fuse操作会加上较上层的pool特征值,导致高维特征不能很好得以使用,同时也因为使用较上层的pool特征值,导致FCN对图像大小变化有所要求,如果测试集的图像远大于或小于训练集的图像,FCN的效果就会变差。
训练过程
FCN训练过程分为四个阶段:
较浅层的预测结果包含了更多细节信息。比较2,3,4阶段可以看出,跳级结构利用浅层信息辅助逐步升采样,有更精细的结果。
FCN原理参考连接:
Segnet是用于进行像素级别图像分割的全卷积网络,分割的核心组件是一个encoder 网络,及其相对应的decoder网络,后接一个象素级别的分类网络。
encoder网络:其结构与VGG16网络的前13层卷积层的结构相似。decoder网络:作用是将由encoder的到的低分辨率的feature maps 进行映射得到与输入图像featuremap相同的分辨率进而进行像素级别的分类。
Segnet的亮点:decoder进行上采样的方式,直接利用与之对应的encoder阶段中进行max-pooling时的polling index 进行非线性上采样,这样做的好处是上采样阶段就不需要进行学习。 上采样后得到的feature maps 是非常稀疏的,因此,需要进一步选择合适的卷积核进行卷积得到dense featuremaps 。
SegNet的思路和FCN十分相似,只是Encoder,Decoder(Unsampling)使用的技术不一样。SegNet的编码器部分使用的是VGG16的前13层卷积网络,每个编码器层都对应一个解码器层,最终解码器的输出被送入soft-max分类器以独立的为每个像素产生类别概率。
左边是卷积提取特征,通过pooling增大感受野,同时图片变小,该过程称为Encoder,右边是反卷积(在这里反卷积与卷积没有区别)与unsampling,通过反卷积使得图像分类后特征得以重现,upsampling还原到原图想尺寸,该过程称为Decoder,最后通过Softmax,输出不同分类的最大值,得到最终分割图。
Encoder编码器
Decoder解码器
使用最大池化的索引进行上采样
U-net对称语义分割模型,该网络模型主要由一个收缩路径和一个对称扩张路径组成,收缩路径用来获得上下文信息,对称扩张路径用来精确定位分割边界。U-net使用图像切块进行训练,所以训练数据量远远大于训练图像的数量,这使得网络在少量样本的情况下也能获得不变性和鲁棒性。
Encoder:左半部分,由两个3x3的卷积层(RELU)+2x2的max pooling层(stride=2)反复组成,每经过一次下采样,通道数翻倍;
Decoder:右半部分,由一个2x2的上采样卷积层(RELU)+Concatenation(crop对应的Encoder层的输出feature map然后与Decoder层的上采样结果相加)+2个3x3的卷积层(RELU)反复构成;
最后一层通过一个1x1卷积将通道数变成期望的类别数。
基于全卷积对称语义分割模型得到的分割结果比较粗糙,忽略了像素与像素之间的空间一致性关系。于是Google提出了一种新的扩张卷积语义分割模型,考虑了像素与像素之间的空间一致性关系,可以在不增加数量的情况下增加感受野。
Deeplabv1是由深度卷积网路和概率图模型级联而成的语义分割模型,由于深度卷积网路在重复最大池化和下采样的过程中会丢失很多的细节信息,所以采用扩张卷积算法增加感受野以获得更多上下文信息。考虑到深度卷积网路在图像标记任务中的空间不敏感性限制了它的定位精度,采用了完全连接条件随机场(Conditional Random Field, CRF)来提高模型捕获细节的能力。
Deeplabv2予以分割模型增加了ASPP(Atrous spatial pyramid pooling)结构,利用多个不同采样率的扩张卷积提取特征,再将特征融合以捕获不同大小的上下文信息。
Deeplabv3语义分割模型,在ASPP中加入了全局平均池化,同时在平行扩张卷积后添加批量归一化,有效地捕获了全局语义信息。
DeepLabV3+语义分割模型在Deeplabv3的基础上增加了编-解码模块和Xception主干网路,增加编解码模块主要是为了恢复原始的像素信息,使得分割的细节信息能够更好的保留,同时编码丰富的上下文信息。增加Xception主干网络是为了采用深度卷积进一步提高算法的精度和速度。在inception结构中,先对输入进行11卷积,之后将通道分组,分别使用不同的33卷积提取特征,最后将各组结果串联在一起作为输出。
主要特点:
在多尺度上为分割对象进行带洞空间金字塔池化(ASPP)
通过使用DCNNs(空洞卷积)提升了目标边界的定位
降低了由DCNN的不变性导致的定位准确率
RefineNet采用了通过细化中间激活映射并分层地将其链接到结合多尺度激活,同时防止锐度损失。网络由独立的RefineNet模块组成,每个模块对应于ResNet。
每个RefineNet模块由三个主要模块组成,即剩余卷积单元(RCU),多分辨率融合(MRF)和链剩余池(CRP)。RCU块由一个自适应块组成卷积集,微调预训练的ResNet权重对于分割问题。MRF层融合不同的激活物使用卷积上采样层来创建更高的分辨率地图。最后,在CRP层池中使用多种大小的内核用于从较大的图像区域捕获背景上下文。
主要特点:
深度卷积神经网络的每一层特征对语义分割都有影响,如何将高层特征的语义信息与底层识别的边界与轮廓信息结合起来是一个具有挑战性的问题。
金字塔场景稀疏网络语义分割模型(Pyramid Scene Parsing Network,PSP)首先结合预训练网络 ResNet和扩张网络来提取图像的特征,得到原图像 1/8 大小的特征图,然后,采用金字塔池化模块将特征图同时通过四个并行的池化层得到四个不同大小的输出,将四个不同大小的输出分别进行上采样,还原到原特征图大小,最后与之前的特征图进行连接后经过卷积层得到最后的预测分割图像。
主要特点:
生成对抗网络模型(Generative Adversarial Nets,GAN)同时训练生成器 G 和判别器 D,判别器用来预测给定样本是来自于真实数据还是来自于生成模型。
利用对抗训练方法训练语义分割模型,将传统的多类交叉熵损失与对抗网络相结合,首先对对抗网络进行预训练,然后使用对抗性损失来微调分割网络,如下图所示。左边的分割网络将 RGB 图像作为输入,并产生每个像素的类别预测。右边的对抗网络将标签图作为输入并生成类标签(1 代表真实标注,0 代表合成标签)。
参考链接:https://cloud.tencent.com/developer/article/1589733
对于常见的语义分割模型,推荐可以直接使用segmentation_models_pytorch库完成:
import segmentation_models_pytorch as smp
model = smp.Unet(
encoder_name="resnet34", # choose encoder, e.g. mobilenet_v2 or efficientnet-b7
encoder_weights="imagenet", # use `imagenet` pre-trained weights for encoder initialization
in_channels=1, # model input channels (1 for gray-scale images, 3 for RGB, etc.)
classes=3, # model output channels (number of classes in your dataset)
)
本章对常见的语义分割网络模型进行介绍,并使用segmentation_models_pytorch完成具体调用。
1.理解语义分割模型构造过程,特别是最终概率值的输出;
y_pred的结果是形状为(IMAGE_SIZE,IMAGE_SIZE),值为 ( − ∞ , + ∞ ) (-∞,+∞) (−∞,+∞)之间
dice = dice_fn(y_pred.sigmoid(), y_true)
由于传入前还作了下sigmoid(),于是y_pred.sigmoid()的值阈为 ( 0 , 1 ) (0,1) (0,1)
这就是每个点的概率,概率越大,就越可能是1
2.加粗样式理解FCN的网络模型结构和训练过程
仔细阅读3.2节就能明白了。
二叉树的深度 题目描述输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。例如:给定二叉树 [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7返回它的最大深度 3 。提示:节点总数 <= 10000来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/er-cha-shu-de-
本系列笔记为方便日后自己查阅而写,更多的是个人见解,也算一种学习的复习与总结,望善始善终吧~马尔科夫矩阵Markov Matrix 马尔科夫矩阵Markov Matrix有两个性质:所有元素大于等于0,所有矩阵的列相加等于1。这里性质导致一些有趣的特性:马尔科夫矩阵Markov Matrix 的幂依然是马尔科夫矩阵Markov Matrix马尔科夫矩阵Markov Matrix的其中一个特
在新公司使用了近两个月的windows开发,那是真的难受~~下周准备带自己的笔记本去上班,闲话少叙日常开发过程中,经常会用到一些adb的指令 比如从手机存储中pull一个log文件到pc,虽然代码不多,但毕竟懒才是推动程序员进步的源泉,我将cmd指令 adb pull /sdcard/xx.log D:/Temp/ 写成批处理文件 @echo off IF EXIST C:\Us
Kinect开发学习笔记之(一)Kinect介绍和应用[email protected]://blog.csdn.net/zouxy09 一、Kinect简介 Kinectfor Xbox 360,简称 Kinect,是由微软开发,应用于Xbox 360 主机的周边设备。它让玩家不需要手持或踩踏控制器,而是使用语音指令或手势来操作 Xbox360
`netstat` 这个命令一直以为是 net status 的缩写,今天一查发现并没有找到官方的这种说法,然后参考了 man 手册,发现这个词更像是 net statistics 的缩写,命令的作用是显示网络连接、路由表、接口连接、无效连接和多播成员关系的...
主题主题是一种定制Blockly外观和感觉的方法。目前我们支持在块和类别上自定义某些样式。我们创建主题的主要目标是授权开发人员创建更容易访问的块体验。然而,伴随着强大的力量而来的是巨大的责任。如果不需要控制块的所有三种样式值(块颜色、边框颜色和阴影块颜色),我们强烈建议用户坚持使用块颜色。很难找到协调一致的颜色,所以最简单的方法仍然是使用色调定义颜色,并允许Blockly计算边框和阴影块的...
导入之后直接访问[url]http://localhost:8080/PageTurning/userList.do[/url]即可
2019.6.15 #程序员笔试必备# LeetCode 从零单刷个人笔记整理(持续更新)题目要求O(log n),很明显需要用二分查找来做。不过分类逻辑却需要思考一下。每次对半截断后,数组可能有两种情况,一种是包含翻转分界的子数组(头元素大于尾元素),另一种是正常升序的数组。在翻转数组中,又分为target位于翻转边界前和位于翻转边界后两种情况。分类完成后,按照正常的二分算法处理即可。...
文章目录CCNP2交换:生成树:STP(802.1D)、PVST、PVST+、RSTP/RPVST、802.1W、MSTP一、线路冗余导致的问题:1、广播风暴2、MAC地址表翻滚:3、同一数据帧的重复拷贝:二、STP生成树:1、STP概述:2、STP的数据帧:BPDU3、IEEE802.1D算法:(1)IEEE802.1D工作过程:(2)IEEE802.1D角色选举算法:(3)IEEE802.1D...
JSON.parse(JSON.stringify(this.list))完美解决参考:https://blog.csdn.net/weixin_47389477/article/details/107691234
Python + opencv 读取视频的三种情况:情况一:通过摄像头采集视频情况二:通过本地视频文件获取视频情况三:通过摄像头录制视频,再读取录制的视频摄像头采集、本地视频文件的读取、写视频文件,网上都有代码。我发现情况一和情况三都没有问题,大家注意读取自己通过摄像头录制的视频文件是没有问题的。但读取其他视频都会发现帧率为0(如果你获取视频的帧率并打印出来的话),并且退出读取。这时候读取是不成功...
题目链接 火车站的列车调度铁轨的结构如下图所示。 两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度? 输入格式: 输入第...