Invertible-Image-Rescaling 代码逐行精读:从 IRNModel 到 ConvDownsampling 的可逆网络实现细节
【免费下载链接】Invertible-Image-Rescaling[ECCV 2020, IJCV 2022] Invertible Image Rescaling项目地址: https://gitcode.com/gh_mirrors/in/Invertible-Image-Rescaling
在 ECCV 2020 的 Invertible-Image-Rescaling(IRN)项目中,可逆图像缩放做到了"一个网络同时搞定下采样与上采样":前向得到低分辨率图 + 潜在噪声 z,反向拼上 z 就能精确恢复高分辨率图。下面我们从训练入口 IRNModel 一路精读到 ConvDownsampling,把可逆网络的每一块拆解清楚。🔍
一、整体架构:一个网络,两个方向
整张图可以拆成三段,正好对应源码里的三类模块:
| 架构组件 | 源码位置 | 作用 |
|---|---|---|
| Haar 变换 / 卷积下采样 | HaarDownsampling、ConvDownsampling | 把分辨率降下来,通道数乘 4(或 scale²) |
| InvBlock 可逆块 | InvBlockExp | 用 F、G、H 三个子网做可逆变换 |
| 下采样模块 | InvRescaleNet | 把上述操作串成整张网络 |
二、项目结构与入口
代码分为 Config / Data / Model / Network 四部分(见 codes/README.md):
- 训练/测试入口:
python train.py -opt options/train/train_IRN_x4.yml、python test.py -opt options/test/test_IRN_x4.yml - 网络定义:codes/models/networks.py
- 模型逻辑:codes/models/IRN_model.py
- 可逆结构:codes/models/modules/Inv_arch.py
- 子网(DBNet 稠密块):codes/models/modules/Subnet_constructor.py
- 训练配置示例:codes/options/train/train_IRN_x4.yml
三、IRNModel:可逆网络的训练核心
IRNModel 继承自 BasicSR 风格的BaseModel,是整个可逆图像缩放模型的"大脑"。
3.1 网络构建与调度器
在__init__中,模型通过networks.define_G(opt)拿到 InvRescaleNet,并按配置选择MultiStepLR或带重启的余弦退火学习率,优化器为 Adam(lr 2e-4)。
3.2 一次训练迭代发生了什么
optimize_parameters是理解 IRN 的关键,共三步:
- 前向下采样:把 HR 图喂给
netG(x=self.input),输出前 3 个通道当作 LR,后scale²-1×3 个通道当作潜在变量 z; - 加噪:对 LR 先做 8bit 量化(Quantization 模块用
round/255模拟真实存储),再按概率叠加高斯噪声,模拟真实下采样器的输出; - 反向放大:把 LR + 随机 z 拼成
y,调用netG(x=y, rev=True)重建 HR,用 L1 损失监督。
总损失为:lambda_fit_forw * L_fit(拟合参考 LR) + lambda_ce_forw * ‖z‖²(z 应接近 0 均值) + lambda_rec_back * L_rec(重建 HR)。
3.3 推理接口
downscale(HR):前向取前 3 通道并量化,得到 LR;upscale(LR, scale):拼上标准高斯 z 后反向传播一次,取前 3 通道得到 HR。
四、InvBlockExp:可逆块的 F/G/H 三剑客
可逆图像缩放的最小单元是 InvBlockExp,它把特征沿通道切成两半:
正向: y1 = x1 + F(x2) s = clamp * (sigmoid(H(y1)) * 2 - 1) y2 = x2 * exp(s) + G(y1) 反向: s = clamp * (sigmoid(H(x1)) * 2 - 1) y2 = (x2 - G(x1)) / exp(s) y1 = x1 - F(y2)每步都只做加法和乘除,因此正向与反向可以互相精确抵消;jacobian()返回±sum(s),即逐点雅可比行列式的对数,供流模型场景使用。F/G/H 由subnet_constructor注入,本项目中是 DenseBlock——5 个卷积串联、逐层拼接特征的 DenseNet 风格子网,最后一个卷积零初始化,保证初始时子网输出为 0(变换为恒等)。
五、ConvDownsampling:可卷积下采样的逐行精读
当use_ConvDownsampling: True(如 train_IRN_x8.yml)时,define_G 会强制down_first=True、down_num=1,网络开头先用一个 ConvDownsampling 直接降 scale 倍。它比固定 2 倍的 Haar 更通用:
- 权重初始化:
conv_weights = torch.eye(scale²);scale=2 时改成 Haar 的 ±1/4 四行权重,scale=3 时第一行取均匀 1/9(低通); - 正向:先用
ReplicationPad2d补齐到 scale 的整数倍,再用 reshape + permute 把scale×scale邻域拉平(类似 pixel-unshuffle),与scale²×scale²的分组卷积做通道混合,输出通道数变为C*scale²; - 反向:直接对权重求矩阵逆
torch.inverse(conv_weights),走一遍卷积 + pixel-shuffle 即可精确还原——这就是"可逆"的来源:下采样是通道间的线性变换,求逆就是上采样。
对比之下,HaarDownsampling 只固定降 2 倍:把不可学习的 Haar 矩阵(A/H/V/D 四通道)作为深度卷积权重,stride=2 完成下采样,反向用转置卷积精确还原。
六、InvRescaleNet:把操作串成一张可逆链
InvRescaleNet 用一个ModuleList顺序存放所有操作:
down_first=True(IRN+ / x3、x8):先放下采样模块,再放block_num[0]个 InvBlock;- 否则:交替放置 Haar 下采样与 InvBlock,逐层降分辨率。
forward的精髓只有一行:正向按operations顺序执行,反向按reversed(operations)逆序执行——每一步自身可逆,整条链自然可逆。🔄
七、定量与定性效果
2× 下采样时,IRN 在 Set5 上达到43.99 dB / 0.9871,参数仅 1.66M,全面超过 CAR+EDSR 等 50M 级组合;4× 时同样以 4.35M 参数取得各数据集最优,验证了这套"可逆块 + 可逆下采样"设计的表达力。
八、快速上手清单
- 安装依赖:
pip install numpy opencv-python lmdb pyyaml+ PyTorch/CUDA; - 修改 options/train/train_IRN_x4.yml 中
dataroot_GT指向 DIV2K 高清图; - 运行
python train.py -opt options/train/train_IRN_x4.yml开始训练; - 换
options/test/test_IRN_x4.yml执行python test.py即可评测; - 彩色与压缩扩展版入口分别为 train_IRN-Color.py 和 train_IRN-Compression.py。
小结
IRN 的可逆图像缩放实现非常克制:可逆性由InvBlockExp的加法-缩放结构和ConvDownsampling的可逆矩阵保证,IRNModel负责前向拟合 + 反向重建的双向训练,InvRescaleNet只做"正向顺序执行、反向逆序执行"的调度。读懂 Inv_arch.py 这不到 300 行代码,基本就掌握了整个项目的精华。✨
【免费下载链接】Invertible-Image-Rescaling[ECCV 2020, IJCV 2022] Invertible Image Rescaling项目地址: https://gitcode.com/gh_mirrors/in/Invertible-Image-Rescaling
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考