语义分割 FCN

图像语义分割

图像语义分割是计算机视觉中十分重要的领域,它是指像素级地识别图像,即标注出图像中每个像素所属的对象类别

语义分割对图像中每一个像素点进行分类,确定每个点的类别

与实例分割的区别

语义分割没有分离同一类的实例;我们关心的只是每个像素的类别,如果输入对象中有两个相同类别的对象,则分割本身不将他们区分为单独的对象。而实例分割会对每一个个体进行单独划分。

应用

  1. 自动驾驶汽车
  2. 医学图像诊断
  3. 无人机着陆点判断

图像语义分割实质

语义分割的目标

一般是将一张RGB图像(height * width * 3)或是灰度图(height * width *1)作为输入

输出的是分割图,其中每一个像素包含了其类别的标签(height * width *1)

1、全卷积网络(FCN)的简单介绍

1.1、CNN与FCN的比较

CNN: 在传统的CNN网络中,在最后的卷积层之后会连接上若干个全连接层,将卷积层产生的特征图(feature map)映射成为一个固定长度的特征向量。一般的CNN结构适用于图像级别的分类和回归任务,因为它们最后都期望得到输入图像的分类的概率,如ALexNet网络最后输出一个1000维的向量表示输入图像属于每一类的概率。如下图所示:
在这里插入图片描述

在CNN中, 猫的图片输入到AlexNet, 得到一个长为1000的输出向量, 表示输入图像属于每一类的概率, 其中在“tabby cat”这一类统计概率最高, 用来做分类任务。

FCN: FCN是对图像进行像素级的分类(也就是每个像素点都进行分类),从而解决了语义级别的图像分割问题。与上面介绍的经典CNN在卷积层使用全连接层得到固定长度的特征向量进行分类不同,FCN可以接受任意尺寸的输入图像,采用反卷积层对最后一个卷基层的特征图(feature map)进行上采样,使它恢复到输入图像相同的尺寸,从而可以对每一个像素都产生一个预测,同时保留了原始输入图像中的空间信息,最后奇偶在上采样的特征图进行像素的分类。如下图所示:

在这里插入图片描述

简单的说,FCN与CNN的区别在于FCN把CNN最后的全连接层换成卷积层,其输出的是一张已经标记好的图,而不是一个概率值。

感受域

在卷积神经网络中,决定某一层输出结果中一个元素所对应的输入层的区域大小,被称作感受野。通常来说,大感受野的效果要比小感受野的效果更好。由公式可见,stride越大,感受野越大。但是过大的stride会使feature map保留的信息变少。因此,在减少stride的情况下,如何增大感受野或使其保持不变,成为了分割中的一大问题。

RFl+1=RFl+(kernel_size-1)x stride

2、FCN上采样理论讲解

FCN网络一般是用来对图像进行语义分割的,于是就需要对图像上的各个像素进行分类,这就需要一

以下是使用PaddlePaddle实现语义分割FCN的示例代码: ```python import paddle import paddle.nn as nn class FCN8s(nn.Layer): def __init__(self, num_classes=21): super(FCN8s, self).__init__() # conv1 self.conv1_1 = nn.Conv2D(3, 64, 3, 1, 100) self.conv1_2 = nn.Conv2D(64, 64, 3, 1, 100) self.pool1 = nn.MaxPool2D(2, 2, 'ceil') # conv2 self.conv2_1 = nn.Conv2D(64, 128, 3, 1, 100) self.conv2_2 = nn.Conv2D(128, 128, 3, 1, 100) self.pool2 = nn.MaxPool2D(2, 2, 'ceil') # conv3 self.conv3_1 = nn.Conv2D(128, 256, 3, 1, 100) self.conv3_2 = nn.Conv2D(256, 256, 3, 1, 100) self.conv3_3 = nn.Conv2D(256, 256, 3, 1, 100) self.pool3 = nn.MaxPool2D(2, 2, 'ceil') # conv4 self.conv4_1 = nn.Conv2D(256, 512, 3, 1, 100) self.conv4_2 = nn.Conv2D(512, 512, 3, 1, 100) self.conv4_3 = nn.Conv2D(512, 512, 3, 1, 100) self.pool4 = nn.MaxPool2D(2, 2, 'ceil') # conv5 self.conv5_1 = nn.Conv2D(512, 512, 3, 1, 100) self.conv5_2 = nn.Conv2D(512, 512, 3, 1, 100) self.conv5_3 = nn.Conv2D(512, 512, 3, 1, 100) self.pool5 = nn.MaxPool2D(2, 2, 'ceil') # fc6 self.fc6 = nn.Conv2D(512, 4096, 7) self.drop6 = nn.Dropout(p=0.5) # fc7 self.fc7 = nn.Conv2D(4096, 4096, 1) self.drop7 = nn.Dropout(p=0.5) # score_fr self.score_fr = nn.Conv2D(4096, num_classes, 1) # upsample2 self.upscore2 = nn.Conv2DTranspose(num_classes, num_classes, 4, 2, 1) # fuse_pool4 self.score_pool4 = nn.Conv2D(512, num_classes, 1) self.fuse_pool4 = nn.Conv2D(num_classes, num_classes, 3, 1, 1) # upsample_pool4 self.upscore_pool4 = nn.Conv2DTranspose(num_classes, num_classes, 4, 2, 1) # fuse_pool3 self.score_pool3 = nn.Conv2D(256, num_classes, 1) self.fuse_pool3 = nn.Conv2D(num_classes, num_classes, 3, 1, 1) # upsample8 self.upscore8 = nn.Conv2DTranspose(num_classes, num_classes, 16, 8, 0) def forward(self, x): # conv1 x = self.conv1_1(x) x = self.conv1_2(x) x = self.pool1(x) # conv2 x = self.conv2_1(x) x = self.conv2_2(x) x = self.pool2(x) # conv3 x = self.conv3_1(x) x = self.conv3_2(x) x = self.conv3_3(x) x = self.pool3(x) # conv4 conv4_1 = self.conv4_1(x) conv4_2 = self.conv4_2(conv4_1) conv4_3 = self.conv4_3(conv4_2) x = self.pool4(conv4_3) # conv5 conv5_1 = self.conv5_1(x) conv5_2 = self.conv5_2(conv5_1) conv5_3 = self.conv5_3(conv5_2) x = self.pool5(conv5_3) # fc6 x = self.fc6(x) x = self.drop6(x) # fc7 x = self.fc7(x) x = self.drop7(x) # score_fr x = self.score_fr(x) # upsample2 upscore2 = self.upscore2(x) # fuse_pool4 score_pool4 = self.score_pool4(conv4_3) fuse_pool4 = self.fuse_pool4(score_pool4[:, :, 5:5 + upscore2.shape[2], 5:5 + upscore2.shape[3]]) x = upscore2 + fuse_pool4 # upsample_pool4 upscore_pool4 = self.upscore_pool4(x) # fuse_pool3 score_pool3 = self.score_pool3(conv3_3) fuse_pool3 = self.fuse_pool3(score_pool3[:, :, 9:9 + upscore_pool4.shape[2], 9:9 + upscore_pool4.shape[3]]) x = upscore_pool4 + fuse_pool3 # upsample8 x = self.upscore8(x) return x ``` 这是一个简单的FCN8s模型,它由卷积层、池化层、全连接层和反卷积层组成。在训练过程中,可以使用交叉熵损失函数和Adam优化器对模型进行训练。具体的代码实现可以参考PaddlePaddle的官方文档和示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值