FCN-8s源码理解

        FCN网络用于对图像进行分割,由于是全卷积网络,所以对输入图像的分辨率没有要求。本文重点对fcn8s.py中图像降采样和上采样后图像分辨率的变换进行理解。

相关知识

       为准确理解图像分辨率的变换,对网络结构中影响图像分辨率变换的几个函数进行简单回顾

  • nn.Conv2d的参数详见这里,其输入和输出之间的关系如下,其中dilation默认为1.
     
  • nn.MaxPool2d的参数详见这里,其输入和输出之间的关系如下:
  • nn.ConvTranspose2d的参数详见这里,其输入和输出之间的关系如下,其中dilation默认为1

Hout =(Hin−1)×stride[0]−2×padding[0]+dilation[0]×(kernel_size[0]−1)+output_padding[0]+1

Wout=(Win−1)×stride[1]−2×padding[1]+dilation[1]×(kernel_size[1]−1)+output_padding[1]+1

网络模型中特征图
  • 前两次上采样均是针对中间特征图进行的,故计算过程一样,只是在特征合并时偏移量不同,这主要是因为前向传播时经历的网络层不一样。此处重点以第一次上采样为例子,介绍偏移量的由来:第一次上采样后进行合并时5个像素的偏移量是如何来的。首先该部分模型代码和网络层参数如下:
A.网络结构
        pool4 = h  # 1/16

        h = self.relu5_1(self.conv5_1(h))
        h = self.relu5_2(self.conv5_2(h))
        h = self.relu5_3(self.conv5_3(h))
        h = self.pool5(h)

        h = self.relu6(self.fc6(h))
        h = self.drop6(h)

        h = self.relu7(self.fc7(h))
        h = self.drop7(h)

        h = self.score_fr(h)
        h = self.upscore2(h)
        upscore2 = h  # 1/16

        h = self.score_pool4(pool4)
        h = h[:, :, 5:5 + upscore2.size()[2], 5:5 + upscore2.size()[3]]
B.不同网络层的参数
        # conv5
        self.conv5_1 = nn.Conv2d(512, 512, 3, padding=1)
        self.relu5_1 = nn.ReLU(inplace=True)
        self.conv5_2 = nn.Conv2d(512, 512, 3, padding=1)
        self.relu5_2 = nn.ReLU(inplace=True)
        self.conv5_3 = nn.Conv2d(512, 512, 3, padding=1)
        self.relu5_3 = nn.ReLU(inplace=True)
        self.pool5 = nn.MaxPool2d(2, stride=2, ceil_mode=True)  # 1/32

        # fc6
        self.fc6 = nn.Conv2d(512, 4096, 7)
        self.relu6 = nn.ReLU(inplace=True)
        self.drop6 = nn.Dropout2d()

        # fc7
        self.fc7 = nn.Conv2d(4096, 4096, 1)
        self.relu7 = nn.ReLU(inplace=True)
        self.drop7 = nn.Dropout2d()

        self.score_fr = nn.Conv2d(4096, n_class, 1)
        self.score_pool3 = nn.Conv2d(256, n_class, 1)
        self.score_pool4 = nn.Conv2d(512, n_class, 1)

        self.upscore2 = nn.ConvTranspose2d(
            n_class, n_class, 4, stride=2, bias=False)

结合相关知识中,模型中仅如下三行代码对特征图分辨率有影响。

        #假设特征图分辨率中宽高一致,均为I
        h = self.pool5(h)  #池化后特征图分辨率变为I/2

        h = self.relu6(self.fc6(h))  #根据fc6中卷积参数,得到卷积后特征图分辨率为(I/2+2*0-7)/1+1=I/2-6

        …………

        h = self.upscore2(h) #根据upscore2上采样的参数,得到等号左侧特征图分辨率为(I/2-6-1)*2+1*(4-1)+1=I-10

从如上变换可以看到,最后上采样后的特征图分辨率相对于pool4特征图的小了10个像素,所以在进行特征合并时,需要进行偏移10/2=5个像素,即如下代码中参数的由来。

h = h[:, :, 5:5 + upscore2.size()[2], 5:5 + upscore2.size()[3]]
  • 输出时的偏移计算方法如下。
        #由于相对于输入X经conv1_1卷积后得到的I而言,pool4之后输出的特征图分辨率变为I/16
        h = self.upscore2(h)   #(I/16/2-6-1)*2+4=I/16-10  ps:I/16之后还有pool5,故又减小一半
        upscore2 = h  # 1/16

        h = self.score_pool4(pool4)
        h = h[:, :, 5:5 + upscore2.size()[2], 5:5 + upscore2.size()[3]]
        score_pool4c = h  # 1/16

        h = upscore2 + score_pool4c  # 1/16
        h = self.upscore_pool4(h)    #(I/16-10-1)*2+4=I/8-18
        upscore_pool4 = h  # 1/8

        h = self.score_pool3(pool3)
        h = h[:, :,
              9:9 + upscore_pool4.size()[2],
              9:9 + upscore_pool4.size()[3]]
        score_pool3c = h  # 1/8

        h = upscore_pool4 + score_pool3c  # 1/8

        h = self.upscore8(h)    #(I/8-18-1)*8+16=I-136

通过上采样后输出图像的分辨率较conv1_1的减小136个像素,由于conv1_1进行了填充(padding=100)故输入x与卷积后I的关系如下。

self.conv1_1 = nn.Conv2d(3, 64, 3, padding=100) #(x+2*100)-3+1=x+198=I

由于在输入x进行了198像素的填充,然后经网络输出后像素减少136个,所以最后网络上采样得到的结果相对于输入x还是增加了(198-136)=62个像素,故而得到最终结果是。

h = h[:, :, 31:31 + x.size()[2], 31:31 + x.size()[3]].contiguous()

此时最终输出的特征图分辨率与输入x的分辨率保持一致,且网络中与浅层特征进行混合时充分考虑了实际的偏移。

参考文献:

  1. pytorch-fcn
  2. Conv2d — PyTorch 2.1 documentation
  3. MaxPool2d — PyTorch 2.1 documentation
  4. ConvTranspose2d — PyTorch 2.1 documentation

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

leetcode:3. 无重复字符的最长子串

一、题目 二、函数原型 int lengthOfLongestSubstring(char* s) 三、思路 本题就是找最长的无重复字符子串。 两层循环,外层循环控制字串的起始位置,内层循环控制字串的长度。 设置一个长度为256且初始为0的hash表(因为一共有256个字符…

windows----Vmware虚拟机安装ubuntu

双系统来回切有点麻烦,还是安装虚拟机先整个简单的。 1 安装Vmware17虚拟机 虚拟机下载网址,一直下一步就行,更新和加入计划关闭 秘钥:MC60H-DWHD5-H80U9-6V85M-8280D 2 下载ubantu镜像 浙大镜像,自己选择版本吧&a…

灰色关联分析

(相关性分析)反映关系有多么紧密 “在系统发展过程中,若两个因素变化的趋势具有一致性,即同步变化程度较高,即可谓二者关联程度较高;反之,则较低。因此,灰色关联分析方法&#xff0…

STM32 ADC采样调试笔记

最近在搞STM32L051系列一个小MCU,要用这个去采集两路ADC作为输入。期间也碰到过一些问题,顺便记录下。 ADC采集原理不说了,主要采集电压,用数字进行细分,这样就可以知道输入电压多少了,网上也有很多相关文…

Spark中的二分类与多分类问题的解决

机器学习中的分类问题是数据科学中的一个重要领域,而在大数据环境中使用Apache Spark来解决二分类和多分类问题可以更好地处理大规模数据。本文将深入探讨如何使用Spark来解决二分类和多分类问题,包括数据准备、模型选择和性能评估等方面。 二分类问题 …

dnSpy调试工具二次开发1-新增菜单

测试环境: window 10 visual studio 2019 版本号:16.11.15 .net framework 4.8 开发者工具包 下载 .NET Framework 4.8 | 免费官方下载 .net 5开发者工具包 下载 .NET 5.0 (Linux、macOS 和 Windows) 利用git拉取代码(源码地址:Gi…

入库和出库的成本对不上如果如何解决

入库是前期手工录入的车价是对的,出库是根据销售出库单生成的 入库成本和出库成本不一致的解决方法 解决方法: 整车管理——正车库存——库存核算——整车出库 成本核算

Marvelous Designer 各版本安装指南

Marvelous Designer下载链接 https://pan.baidu.com/s/1ZZCraq6w2Z4JPisND8q0jA?pwd0531 1.鼠标右击【Marvelous Designer 12(64bit)】压缩包(win11及以上系统需先点击“显示更多选项”)选择【解压到 Marvelous Designer 12(64bit)】。 2.打开解压后的…

深入了解 RDD

深入了解 RDD 案例 明确需求: 在访问日志中,统计独立IP数量 TOP10 查看数据结构: IP,时间戳,Http,Method,Url…… 明确编码步骤 取出IP,生成一个只有IP的数据集简单清洗统计IP出现…

【小沐学CAD】开源Assimp库导入三维模型(C++、Python)

文章目录 1、简介2、下载编译3、代码测试3.1 C3.2 pyassimp(Python) 结语 1、简介 https://github.com/assimp/assimp Open Asset Import Library 是一个库,用于将各种 3D 文件格式加载为共享的内存格式。它支持 40 多种用于导入的文件格式和…

openssl3.2 - 编译

文章目录 openssl3.2 - 编译概述OpenSSL源码下载编译目标如何编译前置环境 - perl前置环境 - VS前置环境 - NASM快速编译步骤编译 - Quick startInstall PerlInstall NASMUse Visual Studio Developer Command Prompt with administrative privilegesFrom the root of the Open…

I.MX6ULL开发笔记(二)——硬件外设操作

0x01 点亮第一个RGB灯 在文章http://t.csdnimg.cn/EGWt9中有介绍Linux下文件目录,那么在Linux系统下,RGB灯也是一个设备,所以我们需要到/sys目录下去操作这个设备。 之后,我们进入到class目录,这里挂载着开发板上的外…

关于一个热成像仪的总结(一)硬件篇电源电路

1、电源部分 电源部分电路原理是这样的通过3.7V的锂电池供电,用Type-C选用TP4056作为充电电路给电池充电。使用MP2161开关电源作为5转3.3V 电源为MCU供电。 1-1电池 待定 1-2充电管理芯片TP4056 参考datasheet:https://atta.szlcsc.com/upload/publi…

[蓝桥杯学习] 线段树

学习blibli 定义 线段树是一种特殊的平衡二叉查找树,使用线段树,可以实现数据的添加、查找和删除。 树的根结点表示了一个完整的单元区间,左右孩子的区间是将父结点的区间进行二分,左右孩子的区间之和,就是他们的根…

studio3T mongodb 根据查询条件更新字段 或 删除数据

1. mongodb 等于、不等于$ne、不包含 $nin 以及批量更新数据的使用。 业务场景: 在集合中,根据查询条件,更新数据状态。 实现代码: 1. 部门名称为XXX、状态不等于“完好”的、并且不包含这些编码的数据先查询出来2. 再把状态更…

基于Java+SSM+JSP实现全功能电子商城

🍅文末获取源码联系🍅 👇🏻 精彩项目推荐订阅👇🏻 不然下次找不到哟 基于SpringBoot的旅游网站 基于SpringBoot的MusiQ音乐网站 感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及…

解决Android AAPT: error: resource android:attr/lStar not found. 问题

错误信息 /xxx/gjc/.gradle/caches/transforms-2/files-2.1/930c42acd29d295ce5bc495c3b84423e/core-1.9.0/res/values/values.xml:104:5-113:25: AAPT: error: resource android:attr/lStar not found. not found 资源位置 场景 原Android studio中的项目都是在git上面拉的老项…

react-hooks-kit v1 正式发布

evanpatchouli/react-hooks-kit - (npmjs.com) v1.0.0 正式发布! 下载安装 npm i evanpatchouli/react-hooks-it -S官方文档 在 Gitee 阅读在 Github 阅读 概览 这是一个无依赖的轻量级 React Hooks 库,总共有 60 hooks。 它包含了一系列易于使用…

端口被占用:Port 8000 was already in use.

一、前言: APPLICATION FAILED TO START Description: Web server failed to start. Port 8000 was already in use. Action: Identify and stop the process that’s listening on port 8000 or configure this application to listen on another port. Proces…

C#,冒泡排序算法(Bubble Sort)的源代码与数据可视化

排序算法是编程的基础。 常见的四种排序算法是:简单选择排序、冒泡排序、插入排序和快速排序。其中的快速排序的优势明显,一般使用递归方式实现,但遇到数据量大的情况则无法适用。实际工程中一般使用“非递归”方式实现。本文搜集发布四种算法…