Learning Continuous Image Representation with Local Implicit Image Function

article/2025/10/11 3:39:36

1. 简介

文章简称为LIIF,即Local Implicit Image Function,受到了3D视觉里场景或物体的隐式表示思想的启发,主要的想法便是把正常的图像当做是连续的,用神经网络表示这个图像之后,对于图像上的每一个像素点其实就当做了一次查询,从而就能实现图像的超分辨率了,并且还是任意尺度的超分,和Meta-SR的工作取得的效果是一样的,在看本文之前,建议先看一下我写的Meta-SR里面的一些相关研究介绍。

2. 思路

  1. 在本文里,当然不是将图像直接用神经网络表示那么简单,在一般的超分领域,图像将会通过两个步骤进行处理,首先经过特征提取模块得到与输入相同尺寸、更深通道的特征图(本文通道数为64),然后经过上采样得到SR图像。在本文中,保留了前半部分的特征提取模块,也就是说,特征提取模块可以随意更换成不同论文里的方法,如ESDR,RDN等等
  2. 当得到特征图之后,我们可以将其想象成放在一个 [ − 1 , 1 ] [-1,1] [1,1]的平面直角坐标系内,然后对于一张新的任意分辨率的SR图像,其像素都有对应的、所属于这个平面直角坐标系的二维坐标,从而也有对应的一个特征图像素,以及这个像素的通道(可以看成长度为64的一维向量)
  3. 把这个像素通道的特征向量(64)、SR图像的某个像素坐标与特征图像素坐标的相对位置(2)组成一个新的一维向量,当做MLP的输入,然后输出一个一维的长度为3向量,当做这个SR图像的像素应有的值,就实现了超分辨率重建
  4. 有多少个SR像素,就查询多少次MLP,全部查询完之后,就组成了SR图像,而图像的分辨率将不再受网络结构本身的影响,实现了分辨率与图像内容表示的解耦合,即使我想生成一张 10000 ∗ 10000 10000*10000 1000010000像素的超分图像,也不用去考虑显存大小开支,只需要把MLP的batchsize设置的大一点,让它多迭代几次就行了
  5. 当然在具体实现过程中,还有local ensemble,feat_unfold,cell decoding等细微操作,但是总的框架如上所示,其实是比较容易理解的

3. 代码层面的详细理解

3.1 数据处理

以div2k数据集为例,结合本文项目代码(liif)梳理一下训练数据预处理流程:

  1. div2k数据集的高分辨率训练集由800张2K图像组成,每张图像尺寸不一,如 2040 ∗ 1848 , 2040 ∗ 1404 2040*1848,2040*1404 2040184820401404等等,因此需要进行某种归一化处理
  2. 对于每张图像,如果不设置inp_size参数,默认是将其给随机缩放到1-4倍之间,作为crop_lr图像,原图作为crop_hr图像;如果设置inp_size参数(inp_size=48),是先随机生成一个长宽均为 48 − 48 ∗ 4 48-48*4 48484像素之内的占位方框,然后随机扔到原图中框出这部分区域作为crop_hr,然后把这部分区域进行双三次插值缩放到 48 ∗ 48 48*48 4848像素作为crop_lr。可以看到,不管原图像尺寸如何,都给统一变成了crop_hr和crop_lr以便于进行下一步处理(虽然这俩变量尺寸大小对于每张图像也不相同)
  3. 以0.5几率进行左右翻转,上下翻转,对称翻转来数据增强,因此训练集可以复制20倍,这里就相当于用了共16000张图像用来训练了
  4. 对于crop_hr,我们要想将其统一,就得将其精细到像素层次,具体做法是:假定每张图像都统一连续表示与二维的[-1,1]正方形平面坐标系区域内,然后我们就可以根据分辨率大小进行坐标系网格划分(肯定分辨率越高网格就越密)这一个个划分后的坐标系小网格就代表了crop_hr的像素(可以想象,如果crop_hr是正方形,那么划分后的坐标系网格是正方形,如果crop_hr是长方形,那么划分后的坐标系小网格肯定就是长方形了,因为原项目设置了inp_size参数,因此第二步骤的crop_hr和crop_lr都是正方形,后面的讨论就都当做正方形来看待了)
  5. 划分坐标系网格之后,那么以坐标系每个小网格中心点的坐标取值可以确定hr_coord,这个值对应的像素值可以确定hr_rgb,二者一一对应,且共有 4 8 2 − 19 2 2 48^2-192^2 4821922对这样的值,具体多少对每张图像都是不一定的,因为在第二步骤里的那个框是48给随机扩展1-4倍的
  6. 但是这样不要紧,我们在配置里有个sample_q参数(sample_q=2304),意思是对这些hr_coord-hr_rgb对随机取sample_q个,得到正式的hr_coord与hr_rgb,也是在这一步,实现了某种意义上的训练图像归一化,而这样随机取会不会丢失信息呢?感觉不会,因为这些采样点差不多均匀覆盖了坐标系正方形的区域,而 2304 = 4 8 2 2304=48^2 2304=482,取的其实也算是足够多了
  7. 最后对于每张图像,总共提取出四个数值,分别为:
  • crop_lr:大小48*48像素,为2K原图随机框选48-192像素大小区域之后再将该区域缩放,作为低分辨率图像,也是神经网络的输入
  • hr_coord:随机打乱的sample_q个正方形区域内的采样点坐标,均匀覆盖了[-1,1]
  • hr_rgb: 这些采样点坐标对应的真实rgb值,和hr_coord一起作为ground truth
  • cell:平面坐标系内的划分的方格宽度

3.2 网络结构

网络的输入为任意一张低分辨率的图像,输出为对应的我们指定的任意分辨率的图像

  1. 网络接收低分辨率图像后,可以经过encoder,也就是某种超分辨率网络(如ESDR,RDN)的上采样之前的部分,输出相同尺寸大小与某深度(这里是64)的特征图。

大致阅读了ESDR(2017)、RDN(2018)这两篇论文,在单张图像超分辨率(SISR)领域,大致做法就是将低分辨率的输入图像,经过神经网络(如ESDR的残差网络,RDN的稠密残差网络),得到相同尺寸的特征图,其深度高达64,得到之后我们根据需要选择不同的上采样层(比如x2倍,x4倍)来得到超分之后的图像。而在训练过程中,后面的上采样层其实就像是一个可以替换的零部件,因为网络的核心部分都在前面了,如果我想训练一个x4的超分辨率网络,完全可以拿一个x2的训练好的超分辨率网络前面的现成的参数,把后面的上采样层换成x4即可,这样替换之后再训练其实可以更快地达到收敛。

  1. 有了特征图,接下来就是围绕特征图所进行的一系列操作,在此之前,先介绍一下文中所提到的坐标系概念,如图所示,假定我们的特征图的长宽均为4(这里只是方便举例子,实际操作中特征图长宽和输入的低分辨率图长宽一样),那么其实可以将其放在一个限定范围在[-1,1]的二维平面直角坐标系内,这样就仿佛整张图片是连续的,我们要得到更高的分辨率,只需要查询一下想要的高分辨率像素的中心点坐标即可:
    d

举个例子,左图为一张 4 ∗ 4 4*4 44的特征图给放到坐标系之后的样子,第一行第一列像素中心点坐标为(-0.75,-0.75),第一行第二列像素中心点坐标为(-0.75,-0.25)这样子;而如果我们想要将其进行超分重建,比如想要分辨率为 11 ∗ 11 11*11 1111,那么就像右图的样子先设定一个蓝色的框框,放在[-1,1]这个范围内,然后就让这个蓝色框框每个蓝色像素(后面就把超分辨率图的像素统一称作蓝色像素了)的中心点坐标对这个由特征图表示的[-1,1]区域进行采样即可

  1. feat_unfold:在继续深入讲之前,说一下文中提到的feat_unfold的概念,其实我们可以理解为将这张 4 ∗ 4 4*4 44的特征图的深度给加深,比如每个像素原先是64通道,现在给变成 64 ∗ 9 64*9 649个通道,多出来8个通道其实就是每个像素周围一圈周围8个像素的通道,如果是在边缘的话就给padding一圈0,在代码里其实借助nn.functional.unfold函数即可实现,至于这么做的原因,可以理解为每个像素的特征肯定和周围的像素特征有关,我们不妨直接把他们给拼接起来,相当于每个像素不是那么独立
  2. 那么究竟该如何从这个[-1,1]的区域内根据特征图查询蓝色像素点的值呢?是借助MLP实现的,这个MLP的输入其实共有 580 = 64 ∗ 9 + 2 + 2 580=64*9+2+2 580=649+2+2个神经元,其中的 64 ∗ 9 64*9 649代表每一个特征图像素的通道数,一个2是指蓝色像素的相对坐标,另一个2是指cell decoding(这俩后面细讲)

我们想要查询蓝色像素,首先得根据超分图分辨率来确定这个蓝色框框到底长宽为多少,然后生成对应的蓝色像素中心点坐标,在查询的时候,是分批次查询的,比如batchsize设成30000,就代表每一批查询30000个蓝色像素,MLP在具体处理的时候,接收的tensor尺寸其实为(30000,580),输出的tensor尺寸为(30000,3),其中3代表RGB值

  1. 下面就产生了一个像素的对应问题,我有了一个蓝色像素的中心点坐标,该如何确定MLP的输入呢?其实主要需要确定两个方面,一个方面是这个蓝色像素应该对应哪个特征图像素以便于取得其通道(64*9),另一个是相对坐标与cell decoding,这里就是文中所谓的local ensemble部分
  2. 如下图所示其实就能更好理解,对于每一个蓝色像素中心点(左图的蓝色点),首先生成一个以蓝色像素中心点为中心的与特征图像素点一样大的橙色框框,这个橙色框框的四个顶点(粉红色点)其实都有其所属的特征图像素,根据这四个粉红色点就能找到四个特征图像素的中心点(黑色点),然后就能计算四个黑色点与蓝色点的绝对距离向量了(绿色箭头),而这个绝对距离向量我们发现其实x,y坐标的取值最大分别为特征点像素的高与宽,乘以特征点像素长宽就能得到相对距离向量了,也就是MLP所应当输入的相对坐标两个值
    d

上面说的其实是在代码层面的理解,因为借助了grid_sample函数,如果从抽象层面简单理解的话,其实就是上面的右图,像论文里所表示的,根据蓝色点来确定其周围最近的四个特征像素中心点坐标并且计算相对坐标,作为MLP的输入

  1. 但是对于一个蓝色像素,我们发现在上面的步骤中其实能产生四个相对坐标,并且每个相对坐标对应着不同的特征像素,在代码层面来看的话,每一次查询,输入的tensor为(30000,2),代表30000个蓝色像素的中心点,在每一次查询里,其实有四次循环,这四次分别计算出30000个蓝色像素点的左上、右上、左下、右下四个相对坐标与四个特征像素的通道,每次循环计算好之后,都会作为MLP的输入进行前向传播,得到30000个RGB值,作为这个蓝色像素左上、右上、左下、右下四个方向应该的RGB值
  2. 在每次查询中我们的最终目标是得到这30000个像素的RGB值,因为其内部经历了四次循环,其实得到的是这个蓝色像素中心点四个角上的RGB值,而要计算这个蓝色像素究竟是啥RGB值,其实可以做某种权重分配的“插值”即可,在文中是计算了四个矩形区域的面积,哪个区域面积越小,就能得到更大的权重
  3. 其实总的来看,虽然说将图像看做了一个连续的区域,要进行超分辨率重建只需要查询对应蓝色像素中心点坐标所应有的RGB即可,但是在实际的代码执行层面中,却不是简单的吧这个蓝色像素中心点所属的特征像素的通道与相对坐标直接丢入MLP得到RGB,而是丢了四次,计算出四个顶点区域的RGB并且做了插值处理。至于为啥要这么做呢,其实这样可以缓解当相邻两个蓝色像素对应的特征像素不一样时最终图像在视觉上看起来不连续的效果(当然不是彻底解决,只是缓解!因为即使是四个像素,也会存在“跳跃”的现象呀)

3.3 cell decoding

按理说,我在这个连续的[-1,1]范围内查询的蓝色像素中心点坐标所对应的颜色就应当是最终的像素颜色,但是我们忽略了一个问题,那便是:我们毕竟查询的是一个正方形的蓝色像素区域,如果仅仅用这个蓝色像素中心点的颜色来表示这整个蓝色像素的颜色会不会有失偏颇呢?或者我们考虑下这种情况:假定我们第一次去查询一张 2 ∗ 2 2*2 22的超分辨率图像,查询第二象限的时候,也就是左上角的那个像素时,中心坐标为(-0.5,-0.5);如果我们再去查询一张 6 ∗ 6 6*6 66的超分辨率图像的话,第二象限会有9个蓝色像素,那么中间那个蓝色像素的中心点坐标其实也是(-0.5,-0.5),相同的中心点坐标,对应着不同的蓝色像素大小,那么这俩像素最终的颜色应该一个样吗?从直觉上来说是不应该一样的,因为我们不能仅仅用中心点的颜色来代表整个像素的颜色,因为本身这个像素的大小是不确定的,在像素块尺寸越小的时候肯定效果区分不明显,但是一旦像素块变大了情况就不容忽略了!因此,MLP的输入特征数还有2个值的位置,就代表了要查询的这个蓝色像素的大小


http://chatgpt.dhexx.cn/article/1vIcWKh2.shtml

相关文章

【InternImage】Exploring Large-Scale Vision Foundation Models with Deformable Convolutions

基于Deformable Conv的大规模基础模型 特点: 采用Deformable Conv V3 【v2 19论文】CNN模型 背景 大规模的ViT模型借助模型能力在超大规模数据集上取得了非常高的性能,然而大规模CNN模型研究才刚刚开始。 近期CNN研究倾向于使用大的卷积kernel&#…

ImageMol

ai圈也是卷的狠啊~~ 又发现一个全球首个分子图像自监督学习框架来也 分子是维持物质化学稳定性的最小单位。对分子的研究,是药学、材料学、生物学、化学等众多科学领域的基础性问题。 分子的表征学习(Molecular Representation Learning)是…

Morphological image processing

目录 基本思想: 一.集合论基础 1.集合的概念 2.集合间的关系和运算 二.二值形态学的基本运算 1.腐蚀 (1)概念 (2)结构元素形状对腐蚀运算结果的影响 (3)腐蚀运算在物体识别中的应用 2…

实用的图片批量压缩优化工具

ImageOptim ImageOptim 支持 PNG/JPEG/GIF 动画,本质是各种影像优化工具的图形前端:AdvPNG、OptiPNG、Pngcrush、JpegOptim、jpegtran、Gifsicle 和 PNGOUT素材。 ImageOptim软件非常小! 2.6M而已ImageOptim操作非常非常非常快捷&#xff01…

【UNI APP】globalData全局变量

uni-app 在app.vue文件export default里面定义globalData,在当前文件(app.vue)里面获取globalData需要用this.$options.globalData获取,其他文件则用getApp().globalData获取。 this.$options是用来获取自…

uniapp 全局数据(globalData)的设置,获取,更改

因为uniapp基本上都是将页面,或者页面中相同的部分,进行组件化,所以会存在父,子,(子,父)之间的传值的情况,但在某些情况下,可以选择将内容设置为一个全局的变…

微信小程序定义和调用全局变量globalData

先看看文件结构: 1.现在app.js里面定义globalData对应的全局变量 2.然后在其他js文件进行调用。例如在photo.js里面 要注意的是需要在文件开始的时候初始化 app这个对象 //获取应用实例 const app getApp()

微信小程序:globalData和Storage数据存储的错误示例

前言 在小程序登录是,将返回的用户数据,存储在globalData中和storage中。 // 存储的数据是一个对象 wx.setStorageSync(userAuthData, user.data.data); this.globalData.userAuthData user.data.data; 之前,数据更新了,为了避…

uni-app之全局变量globalData的使用

一般访问请求的时候,baseurl我们都会用变量来代替,所以我们一半会把大量这种常用的,但是又不会经常变动的数据变成一个常量--globalData export default {onLaunch: function() {},onShow: function() {console.log(App Show)},onHide: function() {console.log(App Hide)},glo…

微信小程序中的共享数据 : globalData

和vue中的vuex作用相同,都是用于设置给所有页面都可以使用的数据的。 globalData在app.js中,它是一个对象,在里面设置要使用到的共享数据。 我们在其他页面要使用globalData中的数据时,首先如下: let app getApp() …

在uniapp中监听globalData中的值变化

小程序里怎么去监听app.js里的globalData数据变化呢 1、先再app.vue 中定义一个全局数据对象globalData,再对象里定义好相应的属性与属性值 globalData:{count:0 },methods:{watch:function(method,istr){var objthis.globalDataconsole.log(obj)Objec…

微信小程序中全局共享数据globalData的使用

1.全局共享数据 全局共享数据的两种方式 通过Vue原型共享数据通过globalData共享数据vuex本地存储 1)在Vue实例原型属性上添加属性,其他任何页面预想使用,直接使用this获取到, 比如: 主要代码:(在入口文件mian.js中) import request from ./utils/request Vue.prototype.re…

Vue全局共享数据之globalData,vuex,本地存储使用方法

目录 一、globalData 二、vuex存储方式 1.vue2用法,2.vue3用法 三、本地存储 uniapp的数据缓存 写在最前面,把vue能用到的存储方法都整理拿出来,方便阅读以及工作用。🍉🍉🍉可以收藏起来即拿即用 Vue全局共…

微信小程序 | 12.生命周期、globalData全局数据

文章目录 1.小程序的生命周期2.全局数据globalData3.globalData的应用3.1.搭配app.js的onLaunch()存储openid3.2.轮询globalData3.2.1.问题描述 3.2.2.解决方式:轮询globalData 1.小程序的生命周期 小程序生命周期(onLaunch、onShow、onHide、onReady、onLoad、onU…

uniapp 全局静态数据(globalData)的修改和使用

uniapp 全局静态数据(globalData)的修改和使用 全局静态数据: 在App.vue中的调用: this.globalData.systemTitle在App.vue中的修改: this.globalData.systemTitle res.title在pages中调用: let title…

微信小程序全局变量(globalData)和缓存(StorageSync)的区别和用法

globalData和storage的区别 一、app.globalData 是全局变量,下次进入的时候,就要重新获取,一般用于: 1、保存一些可能涉及安全类的数据,例如资源类,每次需要很准确的,就建议用全局变量。 2、…

【分布式】什么是分布式技术?

背景: 初代的服务器架构往往比较简单,应用程序、数据库、文件、代码等所有资源都放在一台服务器上,也就是单机结构。随着企业业务量的增多,一台服务器已经难以满足数据处理的需求了,那么对单机进行“复制粘贴”&#…

(分布式网络)基于残差网络的多光谱全色图像分布式融合框架

贡献: ①基于分布式框架(distributed framework)和residual learning,提出了一种鲁棒性强、泛化性能提高的RDFNet泛锐化模型。 ②提出了一种新的三分支泛锐化结构,其中两个分支分别用于提取MS和PAN图像特征。其中最重要的是第三个分支&…

分布式-分布式服务

微服务API 网关 网关的概念来源于计算机网络,表示不同网络之间的关口。在系统设计中,网关也是一个重要的角色,其中最典型的是各大公司的开放平台,开放平台类网关是企业内部系统对外的统一入口,承担了很多业务&#xf…

C++实现轻量级RPC分布式网络通信框架

前言: 2022/4/14更新:  在我重新回顾这篇文章的时候,我觉得里面内容有点乱,主要还是因为RPC里面涉及到很多概念和知识点。本来代码内容就已经挺抽象了,还要结合各种概念,让人难以阅读,所以特地…