FCN实现语义分割-Pytorch(一)

图像语义分割 FCN图像分割网络详解 图像语义分割 FCN图像分割网络网络详解 阅读详情

目录

0、说明
1、语义分割
2、FCN简介
3、FCN实现语义分割
3.1、网络模型(Model)
3.1.1、模型初始化
3.1.2、权重初始化
3.1.3、前向计算(Forward)
3.2、数据集(Dataset)
3.2.1、自定义Dataset
3.2.2、one-hot编码
3.2.3、数据预处理-数据变换(Transform)
3.2.4、数据加载器(DataLoader)
3.2.5、交叉验证(Cross Validation)
3.3、训练(Train)
3.3.1、学习准则(Criterion)
3.3.2、优化(Optimizer)
3.3.3、指标(Metrics)
3.3.3、混淆矩阵(Confusion Matrix)
3.4、验证(Validate)
3.4.1、模型与参数保存
3.4.2、模型验证
3.4.3、混合训练与验证
3.5、测试(Test)
3.5.1、ROC指标
3.5.2、PR指标
3.5.3、绘制测试结果
3.5.4、网格化标注
4、总结

0、说明

本文侧重于各种技术在语义分割代码中的实践,以及如何把各个部分联合起来,完成一个完整的人工智能任务。具体的技术的理论和原理,需要参考其它资料来了解。

1、语义分割

语义分割,是计算机视觉中的一项技术,用于识别图像中的对象,并为对象进行分类。比如下图中的图像,经过语义分割后被划分为不同的区域,以及每个区域的语义。
语义分割

语义分割工作主要包含以下内容:

  1. 语义识别:对图像中的每一个像素进行分类
  2. 目标定位:识别物体边界
  3. 语义分割:生成分割标签

语义分割目前被应用在地理信息系统,无人驾驶,医疗影像,机器人,人脸识别等诸多领域。

2、FCN 简介

全卷积神经网络(FCN),是一种特殊的卷积神经网络(CNN), 最早出现于2015年的一篇“Fully Convolutional Networks for Semantic Segmentation”论文, 和传统的CNN不同,FCN使用卷积层来代替CNN中的全连接(FC)层,使得整个网络结构中的分层全部为卷积层。FCN中使用的主要技术包含:卷积化(Convolutional),跨步卷积(Strided Convolution),跨层连接(Skip Layer),下采样(CNN中的Pooling)(Downsampling)和上采样(Upsampling)

一个典型的FCN网络

FCN 通过多次Downsampling操作,把数据大小缩放为原始图像大小的1/32,原始图像的特征信息在神经网络传输过程中丢失,导致预测结果的精度损失。针对此问题,FCN最终的打分策略,分为直接打分,联合使用上一次Downsampling结果打分,和联合使用上两次Dowsamping结果打分的策略,分别称为 FCN-32s, FCN-16s和FCN-8s。其中FCN-8s由于使用了前两次Downsampling的结果,所以最终预测的结果的精度通常高于FCN-16s和FCN-32s.

FCN

3、FCN实现语义分割

本文使用Pytorch框架和经典的FCN-8s模型来实现语义分割网络

3.1、网络模型(Model)

3.1.1、模型初始化

网络模型主要分为三部分:卷积层,取代全连接层的卷积层,上采样层

class FCN8s(nn.Module):
    def __init__(self, num_classes):
        super(FCN8s, self).__init__()
        self.num_classes = num_classes
        # 第一层卷积
        self.layer1 = nn.Sequential(
            nn.Conv2d(3, 48, (3, 3), padding=1),
            nn.ReLU(inplace=True),
nn.Conv2d(48, 48, (3, 3), padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2, stride=2, ceil_mode=True)  # Downsampling 1/2
        )

        # 第二层卷积
        self.layer2 = nn.Sequential(
            nn.Conv2d(48, 128, (3, 3), padding=1),
            nn.ReLU(inplace=True),
nn.Conv2d(128, 128, (3, 3), padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2, stride=2, ceil_mode=True)  # Downsampling 1/4
        )

        # 第三层卷积
        self.layer3 = nn.Sequential(
            nn.Conv2d(128, 192, (3, 3), padding=1),
            nn.ReLU(inplace=True),
nn.Conv2d(192, 192, (3, 3), padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2, stride=2, ceil_mode=True)  # Downsampling 1/8
        )

        # 第四层卷积
        self.layer4 = nn.Sequential(
            nn.Conv2d(192, 256, (3, 3), padding=1),
            nn.ReLU(inplace=True),
nn.Conv2d(256, 256, (3, 3), padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2, stride=2, ceil_mode=True)  # Downsampling 1/16
        )

        # 第五层卷积
        self.layer5 = nn.Sequential(
            nn.Conv2d(256, 512, (3, 3), padding=1),
            nn.ReLU(inplace=True),
nn.Conv2d(512, 512, (3, 3), padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(2, stride=2, ceil_mode=True)  # Downsampling 1/32
        )

        # 第六层使用卷积层取代FC层
        self.score_1 = nn.Conv2d(512, num_classes, (1, 1))
        self.score_2 = nn.Conv2d(256, num_classes, (1, 1))
        self.score_3 = nn.Conv2d(192, num_classes, (1, 1))

        # 第七层反卷积
        self.upsampling_2x = nn.ConvTranspose2d(num_classes, num_classes, (4, 4), (2, 2), (1, 1), bias=False)
        self.upsampling_4x = nn.ConvTranspose2d(num_classes, num_classes, (4, 4), (2, 2), (1, 1), bias=False)
        self.upsampling_8x = nn.ConvTranspose2d(num_classes, num_classes, (16, 16), (8, 8), (4, 4), bias=False)

        self._initialize_weights()
}
…
}

如果仔细观察上面的一些数值,会发现这个模型和常见的FCN模型存在一些差异。我们看下这些调整,对模型训练和预测结果的影响。

  • 通道数量的变化
    通常的FCN模型,每一个卷积层的通道数量,从96到 4096,示例模型的通道数量为48到256,整体通道数量上比常见的FCN模型要小很多。通道数量会影响到权重参数的数量,进而影响模型的训练速度。我们降低了通道数量,获得了更快的训练速度,同时在预测上,由于特征数量的下降,也降低了预测的精度。

  • 卷积层数量
    后续改进版的FCN,无论是ResNet还是VGG,在每一个Downsampling之前,会有多个卷积层,示例模型每一个下采样只配了二个卷积层。带来的变化可参考通道数量变化,同样是简化了模型,提升了训练速度,降低了预测的精度。

  • 首次卷积的填充
    在FCN网络模型中,第一个卷积层通常给定100单位的填充。
    卷积计算公式:

Wout = (Win – kernal + 2*padding)/stride + 1, 

其中Wout是卷积后输出的大小,Win是输入大小, kernal是kernal size,padding是填充大小,stride是步长

卷积操作中中为了不改变W和H的大小,通常会采用和卷积核大小匹配的Padding和Stride
在第五层卷积后,输出的大小Wout = Win / 32, 接下来的卷积层通常采用大卷积核(比如7)来进行打分,那么根据卷积输出大小的计算公式,输出结果为Wout = Win / 32 – 7 + 1 = (Win - 192)/32, 此时如果原始图像大小小于192,那么将导致打分函数无法计算。而首次Pading从1增加到100,打分之前的输出结果会变成(Win + 2*100 – 2) / 32, 打分的输出也变成了Wout = (Win + 6)/32, 此时原始图像大小不受限制,但引入了过多的噪声,导致预测的精度会有所下降。

为了简化,我们在打分卷积层使用了大小为1的卷积核,那么打分的输出就变成了Wout = Win /32 -1 + 1 = Win / 32, 此时没有原始图像大小受限制的问题,同时由于卷积核变小,也提升了训练速度。

  • 反卷积层
    反卷积计算公式是卷积计算公式的反函数,额外多出了一个output_padding 参数:
Wout = (Win - 1)* stride + kernal - 2 * padding + output_padding

反卷积函数,通过Strided Convolution,配合合理的参数,能够实现特定倍数的Upsampling操作。

3.1.2、权重初始化

权重初始化涉及到为卷积层以及反卷积层的神经元初始化默认值。如果网络模型是已知的模型,比如VGG或ResNET,那么通常使用预训练好的参数来初始化默认权重值,我们使用了自己修改的网络模型,所以这里对权重做下手工初始化

class FCN8s(nn.Module):
    …
    @staticmethod
    def bilinear_kernel(in_channels, out_channels, kernel_size):
        factor = (kernel_size + 1) // 2
        if kernel_size % 2 == 1:
            center = factor - 1
        else:
            center = factor - 0.5
        og = np.ogrid[:kernel_size, :kernel_size]
        filt = (1 - abs(og[0] - center) / factor) * \
               (1 - abs(og[1] - center) / factor)
        weight = np.zeros((in_channels, out_channels, kernel_size, kernel_size),
                          dtype=np.float64)
        weight[range(in_channels), range(out_channels), :, :] = filt
        return torch.from_numpy(weight).float()

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                torch.nn.init.xavier_uniform_(m.weight)
                if m.bias is not None:
                    m.bias.data.zero_()
            if isinstance(m, nn.ConvTranspose2d):
                assert m.kernel_size[0] == m.kernel_size[1]
                initial_weight = self.bilinear_kernel(
                    m.in_channels, m.out_channels, m.kernel_size[0])
                m.weight.data.copy_(initial_weight)
      …
}

对于卷积层的权重初始化,使用了xavier初始化方法,反卷积层的权重初始化采用了双线性插值(Bilinear interpolation)算法。

权重初始化这里非常重要,如果处理不当,在反向传播(backward)时可能产生梯度消失或梯度爆炸问题,甚至无法计算梯度。

3.1.3、前向计算(Forward)

前向计算(forward)和反向传播(backward),是模型训练中非常重要的两个组成部分。对于给定的输入,前向计算通过神经网络模型,为输入进行打分。

class FCN8s(nn.Module):
    …
def forward(self, x: torch.Tensor) -> torch.Tensor:
        h = self.layer1(x)
        h = self.layer2(h)
        s1 = self.layer3(h) # 1/8
        s2 = self.layer4(s1) # 1/16
        s3 = self.layer5(s2) # 1/32

        s3 = self.score_1(s3)
        s3 = self.upsampling_2x(s3)
        s2 = self.score_2(s2)
        s2 += s3
        s2 = self.upsampling_4x(s2)
        s1 = self.score_3(s1)
        score = s1 + s2
        score = self.upsampling_8x(score)

        return score
    …
}

假设我们有一个大小为5的输入,Downsampling后的大小会变成3,Upsampling后,大小则变成了6。经过一轮Downsampling和Upsampling,输出的大小发生了变化。我们需要在Upsampling后,对Tensor进行必要的裁减,使得大小不能被32整除的图像,在一轮Downsampling和Upsampling后,能够恢复原来的大小。添加了大小裁减后的代码如下:

class FCN8s(nn.Module):
    …
def forward(self, x: torch.Tensor) -> torch.Tensor:
        h = self.layer1(x)
        h = self.layer2(h)
        s1 = self.layer3(h) # 1/8
        s2 = self.layer4(s1) # 1/16
        s3 = self.layer5(s2) # 1/32

        s3 = self.score_1(s3)
        s3 = self.upsampling_2x(s3)
        s2 = self.score_2(s2)
s2 = s2[:, :, :s3.size()[2], :s3.size()[3]]
        s2 += s3
        s2 = self.upsampling_4x(s2)
        s1 = self.score_3(s1)
s1 = s1[:, :, :s2.size()[2], :s2.size()[3]]
        score = s1 + s2
        score = self.upsampling_8x(score)
score = score [:, :, :x.size()[2], :x.size()[3]]

        return score
    …
}
使用PyTorch进行语义分割 本篇文章使用进行pytorch进行语义分割的实验。 1.什么是语义分割? 语义分割是一项图像分析任务,我们将图像中的每个像素分类为对应的类。 这类似于我们人类在默认情况下一直在做的事情。每当我们看到某些画面时,我们都会尝试“分割”图像的哪一部分属于哪个类/标签/类别。 从本质上讲,语义分割是我们可以在计算机中实现这一点的技术。 您可以在我们关于图像分割的帖子中阅读更多关于分割的内容。 这篇文章... 阅读详情

相关推荐

语义分割系列1-FCN(全卷积网络)(pytorch实现)

本文复现了全卷积网络FCN(Fully Convolutional Networks)论文,使用pytorch框架构建FCN结构,在PascalVOC2012数据集上实现复现。

yumaomi的博客 6945

语义分割 FCN

图像语义分割 图像语义分割是计算机视觉中十分重要的领域,它是指像素级地识别图像,即标注出图像中每个像素所属的对象类别 语义分割对图像中每一个像素点进行分类,确定每个点的类别 与实例分割的区别 语义分割没有分离同一类的实例;我们关心的只是每个像素的类别,如果输入对象中有两个相同类别的对象,则分割本身不将他们区分为单独的对象。而实例分割会对每一个个体进行单独划分。 应用 自动驾驶汽车 医学图像诊断 无人机着陆点判断 图像语义分割实质 语义分割的目标 一般是将一张RGB图像(height * width *

m0_53926478的博客 1374

pytorch 实现语义分割FCN网络(训练代码+预测代码)

一,FCN网络 FCN大致上就是下图这个结构: 原图通过“编码器网络”把图片越缩越小,然后再通过“解码器网络”把图片再进行逐步放大。得到就结果就是一个个不同颜色的颜色块(称之为掩码),每一种颜色代表不同的类别。 FCN中一个很重要的部分---反卷积 图片通过卷积层降低分辨率,提取特征,而反卷积则是把图片重新放大的一个结构。 在语义分割中,必须对反卷积的反卷积核进行参数初始化(这点...

ZJE 3万+

MindSpore社区活动:FCN图像语义分割

FCN主要用于图像分割领域,是一种端到端的分割方法,是深度学习应用在图像语义分割的开山之作。通过进行像素级的预测直接得出与原图大小相等的label map。因FCN丢弃全连接层替换为全卷积层,网络所有层均为卷积层,故称为全卷积网络。全卷积神经网络主要使用以下三种技术:卷积化(Convolutional)使用VGG-16作为FCN的backbone。VGG-16的输入为224*224的RGB图像,输出为1000个预测值。VGG-16只能接受固定大小的输入,丢弃了空间坐标,产生非空间输出。

longvoyage的博客 955

Pytorch实战语义分割(VOC2012)

Pytorch实战语义分割(VOC2012) 本文参照了《动手深度学习》的9.9、9.10章节,原书使用的是 mxnet 框架,本文改成了pytorch代码。 语义分割(semantic segmentation)问题,它关注如何将图像分割成属于不同语义类别的区域。值得一提的是,这些语义区域的标注和预测都是像素级的。 语义分割中图像有关狗、猫和背景的标签 文章目录Pytorch实战语义分割(V...

早睡早起 2万+

Pytorch:图像语义分割-FCN, U-Net, SegNet, 预训练网络

介绍了图像语义分割网络的基本概念,介绍了FCN, U-Net, SegNet的网络结构并用代码实现建模,使用预训练的语义分割网络完成颜色编码和图像分割。

Jingmin Wei's Blog 6893

【语义分割系列】一图讲解FCN16s实现过程。对照着pytorch代码讲解的。

看了下fcn的代码和理论。这里就以FCN16s为例讲解,16s清晰了 32s 8s 只是在此基础上减,加而已了。 我看的代码是一VGG16为主干网络。关键步骤的解释在下图中已标记清晰,对照其他主干网络代码看也都能看的通。 FCN16s说白了就是 将 1/32图的预测结果做反卷积,变成1 /16图。然后再将1 /16图池化结果做预测,并与前的1/32图 结果做加法。最终得到...

gbz3300255的博客 2668

pytorch语义分割

Pytorch语义分割最近整合了部分pytorch实现的图象语义分割模型,简单做一下总结,代码在git:pytorch-semantic-segmentation一、简介    基于深度的图象语义分割任务不同于分类与检测任务,分类任务利用深度模型提取特征后输出特征向量并计算各类概率,简单理解为“一图对应一标记”。检测则在分类任务基础上增加了候选框的生成和回归的任务,模型同时做物体区域定位与区域分类...

a132582的博客 1万+

图像语义分割任务库:mmseg简介

mmsegmentation(简称 mmseg)是 OpenMMLab 开源的计算机视觉库,专注于语义分割任务。它基于 PyTorch 实现,支持多种经典和前沿的语义分割模型(如 FCN、PSPNet、DeepLabV3+、UNet 等),并提供模块化设计,便于快速实验和部署。模块化设计、支持多种模型、丰富的预训练权重。适用场景:语义分割任务(如自动驾驶场景理解、医学图像分割)。扩展性:可轻松替换 Backbone、Head 或损失函数。

GIS摆渡人 1100

深度学习图像语义分割网络总结:FCN与SegNet的Pytorch实现

图像语义分割网络系列博文索引 FCN与SegNet U-Net与V-Net DeepLab系列 DenseNet、PSPNet、与DenseASPP Mask R-CNN (后四个在计划中,敬请期待) 图像语义网络分割之FCN图像语义分割网络系列博文索引全卷积网络FCN主要贡献网络结构Pytorch框架下FCN实现 全卷积网络FCN FCN为深度学习在图像语义分割领域里程碑的一篇,实现了对任意大小输入图像进行像素级别的端到端的语义分割。原文链接:Fully Convolutional Netw

神仙院B栋4楼保安的博客 2971

【语义分割系列:三】FCN 论文阅读翻译笔记+资源整理+pytorch实现

2015 CVPR best paper key word: pixel level, fully supervised, CNN semantic segmentation milestone Fully Convolutional Networks for Semantic Segmentation 官方 github:FCN wkentaro Pytorch FCN Pytorch FC...

鹿鹿的博客 4673

【pytorch】 关于ConvTranspose2d的一点理解

FCN中一个很重要的部分—反卷积 图片通过卷积层降低分辨率,提取特征,而反卷积则是把图片重新放大的一个结构。 在语义分割中,必须对反卷积的反卷积核进行参数初始化(这点很重要)。一般使用的方法是双线性插值法。 pytorch 中反卷积函数的说明:FCN中一个很重要的部分—反卷积 图片通过卷积层降低分辨率,提取特征,而反卷积则是把图片重新放大的一个结构。 在语义分割中,必须对反卷积的反卷积核进行参数初...

weixin_43468458的博客 1366

Pytorch:图像语义分割-基于VGG19的FCN8s实现

实现了基于VGG19 backbone的FCN8s的语义分割,利用该模型在VOC2012数据集上进行图像语义分割的训练,验证和测试。

Jingmin Wei's Blog 4359

【深度学习项目】语义分割-FCN网络(原理、网络架构、基于Pytorch实现FCN网络)

FCN(Fully Convolutional Networks,全卷积网络)是一种用于计算机视觉任务的神经网络架构,尤其擅长处理像素级别的分类问题,例如语义分割。FCN 的核心思想是将传统的 CNN(卷积神经网络)中的全连接层替换为卷积层,这样可以接受任意大小的输入图像,并输出同样大小的概率图,其中每个像素点对应于该位置属于某个类别的概率。

专注上位机开发、机器视觉、机器学习、嵌入式软硬件开发 1万+

语义分割系列3-SegNet(pytorch实现)

本文介绍了SegNet网络结构,基于pytorch构建了SegNet模型,并在Camvid数据集上复现。

yumaomi的博客 1万+

FCN全卷积网络理解及代码实现(来自pytorch官方实现)

FCN是首个端对端的针对像素级预测的全卷积网络 而换为卷积层之后,最后得到的是1000通道的2D图像,可以可视化为heat map图。一般说的vgg16是D: 全连接操作前后:77512(通道) 【假设忽略偏置】\color{red}{【假设忽略偏置】}【假设忽略偏置】 全连接FC1计算:计算对应某一个结点的输出,将该节点与上一层某一个结点的权重与输入对应节点数值相乘,再求和下层使用7*7的卷积核、stride=1,4096个卷积核的一个卷积层一个卷积核和FC1一个节点参数量一样\color{red}{一

m0_46378271的博客 1万+

语义分割——FCN模型pytorch实现

pytorch实现FCN-8s

Stillboring的博客 4842

总结-NuerIPS2023-Direct Preference Optimization:Your Language Model is Secretly a Reward Model

对比PPO,DPO的泛化能力更强。

m0_60361484的博客 1607

基于pytorch的FCN网络简单实现

参考知乎专栏实现FCN网络https://zhuanlan.zhihu.com/p/32506912 import torch from torch import nn import torch.nn.functional as f import torchvision import torchvision.transforms as tfs from torch.utils.data import DataLoader from torch.autograd import Variable import

haohulala的博客 1万+

人工智能之语言领域 自然语言处理 第六章 情感分析

情感分析(Sentiment Analysis),又称意见挖掘(Opinion Mining),旨在自动识别和提取文本中表达的主观情感、态度或情绪。从用户评论到社交媒体,从产品反馈到政治舆情,情感分析已成为企业决策、品牌监控和人机交互的关键技术。本章将深入介绍情感分析的层级结构、核心技术、主流模型,并通过社交媒体舆情实战案例完整演示分析与可视化流程。层级目标示例词级(Word-level)判断单个词的情感倾向“好” → 正面;“差” → 负面句级(Sentence-level)判断整个句子的情感极性。

咚咚王者的博客 857

金证股份软件测试笔试题面试题

boss上这家公司的HR找到了我,我看了一下这家公司的业务,是我以前做过的基金与证券。还是很感兴趣的,决定去面试看看情况。 (因为只是想去涨面试经验,没有想拿offer,一些回答有点不太对,为后面木有offer埋下伏笔。其实有点亏,毕竟走路过去,而且还花了3个小时) 地点在金证股份科技大楼8楼。 2月25号 主要分为笔试题和面试。 1、笔试题 进来的时候直接给我一份笔试题做,做了一个半小时吧。 分为3道选择题和1道SQL查询题、1道案例设计题 选择题都是考察SQL函数,可能日常生活中没有见过

全村的希望的博客 4451
下一篇: FCN实现语义分割-Pytorch(二)
孙晓军82
博客等级 码龄21年 40粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值