图像语义分割 pytorch复现DeepLab v1图像分割网络以及网络详解(骨干网络基于VGG16)

news2024/9/22 19:22:05

图像语义分割 pytorch复现DeepLab v1图像分割网络以及网络详解(骨干网络基于VGG16)

  • 背景介绍
  • 2、 网络结构详解
    • 2.1 LarFOV效果分析
  • 2.2 DeepLab v1-LargeFOV 模型架构
  • 2.3 MSc(Multi-Scale,多尺度(预测))
  • 2.3 以VGG16为特征提取骨干网络代码
  • pytorch实现网络结构项目

背景介绍

论文名称:Semantic Image Segmentation with Deep Convolutional Nets and Fully Connected CRFs

在这里插入图片描述

  • 2014 年发表于 CVPR
  • DeepLab v1 是一种用于语义分割的卷积神经网络模型,其核心思想是结合了全局上下文信息,以更好地理解图像中的语义内容。

论文中指出了当前图像语义分割的存在问题:

  • 下采样会导致图像的分辨率降低
    在 DCNN 中,通常通过池化层来进行信号下采样,这是为了减少特征图的尺寸和参数数量。然而,池化操作会导致特征图的空间分辨率降低,从而损失了一部分细节信息。在图像标注任务中,像素级的细节信息对于准确的标注非常重要,因此信号下采样可能会影响标注的质量。
    在这里插入图片描述
  • 空间不敏感
    DCNNs 在高级视觉任务中表现出色的一个原因是它们具有一定程度的平移、旋转、缩放等空间不变性。然而,对于像素级标注任务(如语义分割或像素级分类),我们希望网络能够对每个像素点进行精细的标注,这就需要网络具有较高的空间敏感性。然而,DCNNs 的不变性特性可能导致在特征提取过程中丢失一些空间信息,使得网络对于像素级标注任务不够敏感。

论文中解决以上两个问题的方案:
在这里插入图片描述

  • 1、采用空洞卷积
  • 2、采用fully-connected CRF(Condition Random Fie)(全连接条件随机场)
    CRF在语义分割领域是常用的方法,但是在DeepLab V3之后便不再使用

网络优势:

  • 速度更快,论文中说因为采用了膨胀卷积的原因,但fully-connect CRF很耗时
  • 准确率更高,相比之前最好的网络,提升了7.2个点
  • 结构简单,主要采用DCNN和CRFs级联构成在这里插入图片描述
    DeepLab:本文提出的语义分割模型
    MSc:Multi-Scale,多尺度
    CRF:全连接条件随机场,用于对图像进行后处理以改善分割或标注的结果。它通常用于在图像分割任务中对神经网络的输出进行精炼和优化
    LargeFOV:空洞卷积

2、 网络结构详解

DeepLab v1 的 Backbone 使用的是 VGG16作为主要的卷积神经网络架构(2014年最牛逼的分类网络为VGG)。在 DeepLab v1 中,VGG16 的部分或全部全连接层被去除,而只保留卷积层,并通过空洞卷积(Atrous Convolution)来增大感受野,从而实现对图像的全局上下文信息的捕获

VGG16 的结构包含 16 层卷积层和全连接层,其中包括 13 个卷积层和 3 个全连接层。该模型在 ImageNet 数据集上进行了训练,并在图像分类任务上取得了很好的性能。

2.1 LarFOV效果分析

在这里插入图片描述
将卷积核减小,比如从原来的 kernel_size = (7, 7) 变为 kernel_size = (4, 4) 或 kernel_size = (3, 3)
在这里插入图片描述

注意❗️

  • 这里替换全连接层的卷积层并非普通卷积层,而是一个膨胀卷积,它有一个膨胀系数 r,可以扩大感受野。
  • 图中的 input stride 其实是膨胀系数 r。

在这里插入图片描述

2.2 DeepLab v1-LargeFOV 模型架构

VGG系列网络结构:
在这里插入图片描述
DeepLab-LargeFOV 模型架构:
在这里插入图片描述

经过上采样得到 224 × 224 × num class的特征图并非模型最终输出结果,还要经过一个 Softmax 层后才是模型最终的输出结果。

Softmax 层的作用是将每个像素的类别预测转换为对应类别的概率。它会对每个像素的 num_classes 个类别预测进行归一化,使得每个预测值都落在 0 到 1 之间,并且所有类别的预测概率之和为 1。这样,对于每个像素点,我们可以得到每个类别的概率,从而确定该像素属于哪个类别的概率最大。最终的输出结果通常是经过 Softmax 处理后的特征图,其中每个像素点都包含了 num_classes 个类别的概率信息。

LargeFOV 本质上就是使用了膨胀卷积。

  • 通过分析发现虽然 Backbone 是 VGG-16 但使用 Maxpool 略有不同,VGG 论文中是 kernel=2,stride=2,但在 DeepLab v1 中是 kernel=3,stride=2,padding=1。接着就是最后两个 Maxpool 层的 stride 全部设置成了 1(这样下采样的倍率就从原来的 32 变成了 8)。最后三个 3 × 3 的卷积层采用了膨胀卷积,膨胀系数 r = 2。
  • 然后关于将全连接层卷积化过程中,对于第一个全连接层(FC1)在 FCN 网络中是直接转换成卷积核大小为 7 × 7,卷积核个数为 4096 的卷积层(普通卷积),但在 DeepLab v1 中作者说是对参数进行了下采样最终得到的是卷积核大小 3 × 3 ,卷积核个数为 1024 的卷积层(膨胀卷积)(这样不仅可以减少参数还可以减少计算量,详情可以看下论文中的 Table2),对于第二个全连接层(FC2)卷积核个数也由 4096 4096 采样成 1024(普通卷积)。
  • 将 FC1 卷积化后,还设置了膨胀系数(膨胀卷积),论文 3.1 中说的是 r = 4 但在 Experimental Evaluation 中 Large of View 章节里设置的是 r = 12 对应 LargeFOV。对于 FC2 卷积化后就是卷积核 1 × 1 ,卷积核个数为 1024 的普通卷积层。接着再通过一个卷积核 1 × 1 ,卷积核个数为 num_classes(包含背景)的普通卷积层。最后通过 8 倍上采样还原回原图大小。

注意❗️采用的是双线性插值(Bilinear Interpolation)的策略来实现上采样,双线性插值会考虑其周围 4 个最近的像素点根据距离权重进行插值计算。这样可以有效地将特征图还原到原始输入图像的大小,使得网络的输出和输入在空间尺寸上保持一致

2.3 MSc(Multi-Scale,多尺度(预测))

即融合多个特征层的输出
DeepLab-LargeFOV-MSc 模型架构
在这里插入图片描述

2.3 以VGG16为特征提取骨干网络代码

DeepLab-LargeFOV

#!/usr/bin/python
# -*- encoding: utf-8 -*-


import torchvision
import torch
import torch.nn as nn
import torch.nn.functional as F


斜体样式
class DeepLabLargeFOV(nn.Module):
    def __init__(self, in_dim, out_dim, *args, **kwargs):
        super(DeepLabLargeFOV, self).__init__(*args, **kwargs)
        # vgg16 = torchvision.models.vgg16()

        layers = []
        layers.append(nn.Conv2d(in_dim, 64, kernel_size = 3, stride = 1, padding = 1))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.Conv2d(64, 64, kernel_size = 3, stride = 1, padding = 1))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.MaxPool2d(3, stride = 2, padding = 1))

        layers.append(nn.Conv2d(64, 128, kernel_size = 3, stride = 1, padding = 1))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.Conv2d(128, 128, kernel_size = 3, stride = 1, padding = 1))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.MaxPool2d(3, stride = 2, padding = 1))

        layers.append(nn.Conv2d(128, 256, kernel_size = 3, stride = 1, padding = 1))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.Conv2d(256, 256, kernel_size = 3, stride = 1, padding = 1))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.Conv2d(256, 256, kernel_size = 3, stride = 1, padding = 1))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.MaxPool2d(3, stride = 2, padding = 1))

        layers.append(nn.Conv2d(256, 512, kernel_size = 3, stride = 1, padding = 1))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.Conv2d(512, 512, kernel_size = 3, stride = 1, padding = 1))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.Conv2d(512, 512, kernel_size = 3, stride = 1, padding = 1))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.MaxPool2d(3, stride = 1, padding = 1))

        # 以下采用膨胀卷积
        layers.append(nn.Conv2d(512,
            512,
            kernel_size = 3,
            stride = 1,
            padding = 2,
            dilation = 2))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.Conv2d(512,
            512,
            kernel_size = 3,
            stride = 1,
            padding = 2,
            dilation = 2))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.Conv2d(512,
            512,
            kernel_size = 3,
            stride = 1,
            padding = 2,
            dilation = 2))
        layers.append(nn.ReLU(inplace = True))
        layers.append(nn.MaxPool2d(3, stride = 1, padding = 1))
        self.features = nn.Sequential(*layers)

        classifier = []
        classifier.append(nn.AvgPool2d(3, stride = 1, padding = 1))
        classifier.append(nn.Conv2d(512,
            1024,
            kernel_size = 3,
            stride = 1,
            padding = 12,
            dilation = 12))
        classifier.append(nn.ReLU(inplace=True))
        classifier.append(nn.Conv2d(1024, 1024, kernel_size=1, stride=1, padding=0))
        classifier.append(nn.ReLU(inplace=True))
        classifier.append(nn.Dropout(p=0.5))
        classifier.append(nn.Conv2d(1024, out_dim, kernel_size=1))
        self.classifier = nn.Sequential(*classifier)

        self.init_weights()


    def forward(self, x):
        N, C, H, W = x.size()
        x = self.features(x)
        x = self.classifier(x)
        x = F.interpolate(x, (H, W), mode='bilinear', align_corners=True)
        return x

    def init_weights(self):
        vgg = torchvision.models.vgg16(pretrained=True)
        state_vgg = vgg.features.state_dict()
        self.features.load_state_dict(state_vgg)

        for ly in self.classifier.children():
            if isinstance(ly, nn.Conv2d):
                nn.init.kaiming_normal_(ly.weight, a=1)
                nn.init.constant_(ly.bias, 0)


if __name__ == "__main__":
    net = DeepLabLargeFOV(3, 10)
    in_ten = torch.randn(1, 3, 224, 224)
    out = net(in_ten)
    print(out.size())

    in_ten = torch.randn(1, 3, 64, 64)
    mod = nn.Conv2d(3,
            512,
            kernel_size = 3,
            stride = 1,
            padding = 2,
            dilation = 2)
    out = mod(in_ten)
    print(out.shape)


    import os
    import torch
    from torchsummary import summary


    os.environ["CUDA_VISIBLE_DEVICES"] = "1"
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    net=DeepLabLargeFOV(3,21).to(device)
    print(summary(net,(3,224,224)))

    print(torch.cuda.current_device())

pytorch实现网络结构项目

项目源代码下载地址
目录结构:
在这里插入图片描述
1、下载数据集,并将数据集存储在以下目录
在这里插入图片描述
2、执行代码:

python train.py --cfg config/pascal_voc_2012_multi_scale.py

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1132051.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

@Inherited注解类

包名package java.lang.annotation; 作用 指示批注类型是自动继承的。如果注释类型声明上存在Inherited元注释,并且用户在类声明上查询注释类型,并且该类声明没有该类型的注释,则将自动查询该类的超类的注释类型。将重复此过程,直…

XQ350441.0、XQ350641.0、XQ350441.1、XQ350641.1、XQ350441.2、XQ350641.2三位五通电磁气动阀

XQ230440、XQ230640、XQ230840、XQ231040、XQ231540二位三通气动电磁阀;XQ250440、XQ250640、XQ250840、XQ251040、XQ251540二位五通电磁气动阀;XQ240440二位四通电磁气动阀;XQ230441、XQ230641、XQ230841、XQ231041、XQ231541二位三通电磁气…

Web APIs——键盘事件以及发布评论

一、事件类型 二、 键盘事件 <body><input type"text"><script>const input document.querySelector(input)input.addEventListener(keydown,function(){console.log(键盘按下了);})input.addEventListener(keyup,function(){console.log(键盘弹…

超大场景的倾斜摄影三维模型的顶层合并构建的必要性分析

超大场景的倾斜摄影三维模型的顶层合并构建的必要性分析 倾斜摄影三维模型的顶层构建是将倾斜摄影数据转换为精确的三维模型的过程。它具有许多重要的应用和意义&#xff0c;本文将介绍几个主要的原因。 一、可视化与漫游 倾斜摄影三维模型的顶层构建可以实现对地理场景的精确…

按照外部形态,构成软件系统的构建一共可以分为五类

独立而成熟的构件 成熟而独立的构件得到了实际运行环境的多次检验&#xff0c; 有限制的构件 提供了接口&#xff0c;指出了使用条件和前提&#xff0c;这种构件在装配时会产生资源冲突&#xff0c;覆盖等影响&#xff0c;在使用时需要加以测试。例如各种面向对象程序设计语言中…

【强化学习】08——规划与学习(采样方法|决策时规划)

文章目录 优先级采样Example1 Prioritized Sweepingon Mazes局限性及改进 期望更新和采样更新不同分支因子下的表现 轨迹采样总结实时动态规划Example2 racetrack 决策时规划启发式搜索Rollout算法蒙特卡洛树搜索 参考 先做个简单的笔记整理&#xff0c;以后有时间再补上细节 …

抽象轻松java——简易图书馆前置

用Maven写一个垃圾的项目&#xff0c;第一步打开IDEA&#xff0c;点击创建&#xff0c;创建一个Maven <dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</versi…

antv x6 沿边图标循环动画实现

实现效果&#xff0c;如下图&#xff0c;边上存在两个图标&#xff0c;要求图标延边一直循环动画 实现方法&#xff1a; 1.注册一个自定义边&#xff0c;边上定义两个图标&#xff0c;并设置其初始位置 2.使用transition给边设置动画,利用complte方法实现循环动画

8年测试老鸟,Python Selenium自动化测试-POM分层封装框架(超全整理)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、POM模式是什么…

【JAVA学习笔记】41 - 接口

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter10/src/com/yinhai/interface_ 一、快速入门 usb插槽就是现实中的接口。你可以把手机&#xff0c;相机&#xff0c;u盘都插在usb插槽上&#xff0c;而不用担心那个插槽是专门插哪个的&#x…

【广州华锐视点】VR塔吊模拟实操考核系统

随着科技的不断发展&#xff0c;虚拟现实技术已经逐渐渗透到各个领域&#xff0c;为人们带来了全新的体验。在建筑行业中&#xff0c;塔吊作为一种重要的起重设备&#xff0c;其拆装作业的安全与否直接关系到工程质量和人员生命安全。为了提高塔吊拆装作业的安全性和效率&#…

VUE3中 reacitive源码理解

Proxy 在Vue里面定义一个响应式函数 reacitive 会通过 Proxy 进行拦截&#xff0c;在截的时候里面有ge和set track get的时候有一个跟踪函数叫 track track里面会收集各种依赖&#xff0c;把依赖关系做成各种映射的关系&#xff0c;映射关系就叫 targetMap&#xff0c;vue内部拿…

ES6初步了解Map对象(含十种方法)

ES6提供了 Map数据结构。它类似于对象&#xff0c;也是键值对的集合。但是“键”的范围不限于字符串&#xff0c;各种类型的值&#xff08;包括对象&#xff09;都可以当作键。 创建方法 let m new Map()console.log(m)Map的方法 1.set( ) 添加元素 接收两个参数&#xff0c…

使用香橙派并基于Linux实现最终版智能垃圾桶项目 --- 下

最终完成效果视频&#xff1a; 使用香橙派并基于Linux实现最终版带图像识别的可回收垃圾桶 — 下_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1bc411o7zS/?spm_id_from333.999.0.0&vd_source16380169fa415d2d056dd877a8d8c1b7 硬件接线 & 最终实现图 目录 …

智能振弦传感器:参数智能识别技术的重要科技创新

智能振弦传感器&#xff1a;参数智能识别技术的重要科技创新 智能振弦传感器是一种能够自动识别传感器参数的高科技产品。它的研发得益于河北稳控科技的不断创新和努力&#xff0c;其电子标签专用读数模块模块TR01将传感器生产和标定过程实现了自动化。该模块将温度电阻两芯线…

单片机中的 _nop_() 延时以及其相关的基础扩展

使用 _nop_() 函数做延时遇到的一些问题 以及对此延伸出的一些需要了解的基本概念 ...... by 矜辰所致 完善文章内容结构&#xff0c;补充指令周期、机器周期等一些基本概念 2023/10/25前言 最近还是继续做着项目&#xff0c;因为在某 8051 内核芯片上使用到了 I…

Windows隐藏计划任务技术

Windows隐藏计划任务技术 0x00 前置知识 计划任务SCHTASKS命令 SCHTASKSSCHTASKS /Create 参数 SCHTASKS /Create [/S system [/U username [/P [password]]]][/RU username [/RP password]] /SC schedule [/MO modifier] [/D day][/M months] [/I idletime] /TN taskname …

手写SDK的秘诀

目录 什么是SDK?使用SDK的好处&#xff1f;手写SDK经验总结易用性如何提高易用性&#xff1f;1、统一调用2、集中配置3、良好的命名 可理解性1、结构清晰2、统一风格3、编写注释4、说明文档 可扩展性轻量依赖自定义实现 高效稳定 写在最后 什么是SDK? SDK&#xff08;Softwa…

记一次大型微服务项目本地打包迁移部署

记一次大型微服务项目本地打包迁移部署 引代码合并发布过程本地部署服务配置服务打包自启动测试外部依赖排除部分外部依赖 引 服务的运维也是一个挺复杂工作&#xff0c;如项目上线后的一次小版本发布&#xff0c;开发人员需要基于工程最新代码拉取feature分支&#xff0c;本地…

CPU性能优化——“瑞士军刀“

背景 最近在做一些工具的预研工作&#xff0c;会涉及到对工具的压力测试&#xff0c;分析工具的资源消耗等问题&#xff0c;其中CPU 资源消耗是关键指标之一。为了后续性能优化做准备&#xff0c;回顾了以前相关CPU优化知识&#xff0c;并做总结分享。希望能帮助到正在遇到相关…