论文信息

  • 标题:DiffBIR: Toward Blind Image Restoration with Generative Diffusion Prior
  • 会议:ECCV 2024
  • 单位:中国科学院深圳先进技术研究院、上海人工智能实验室、香港中文大学、深圳大学等
  • 代码:https://github.com/XPixelGroup/DiffBIR
  • 论文:https://www.ecva.net/papers/eccv_2024/papers_ECCV/papers/07690.pdf

你有没有过这种经历?网上找的老照片糊成马赛克,拍的夜景图满是噪点,放大的人脸五官全是模糊的色块——这些场景,本质上都是盲图像恢复(Blind Image Restoration, BIR) 问题。通俗点说,就是你不知道这张低质图到底经历了什么样的“破坏”(比如模糊、噪声、压缩、下采样,甚至是多种退化叠加),还要把它还原成高清、真实、细节拉满的高质量图。

过去几年,这个领域卷疯了:GAN-based方法(比如Real-ESRGAN、CodeFormer)虽然能快速出图,但要么细节假得生硬,要么只能搞定特定场景(比如人脸),泛化能力拉胯;后来零样本扩散方法来了,靠着DDPM(去噪扩散概率模型,通俗说就是AI靠迭代去噪生成图片的一套算法)的强大生成能力,能出很真实的细节,但又搞不定未知的复杂退化,一遇到真实世界的野图就翻车。

直到ECCV 2024的这篇DiffBIR,直接把BIR问题拆成了“去退化”和“补细节”两个独立阶段,用一套统一框架,同时拿下了盲图像超分(BSR)、盲人脸修复(BFR)、盲图像去噪(BID) 三大核心任务的SOTA,直接成了开源社区最火的扩散恢复模型之一。

一、核心洞察:为什么盲图像恢复这么难?

传统方法要么直接用带退化的低质图做监督训练,要么直接把低质图当条件喂给扩散模型,但都踩了同一个坑:低质图里的退化信息和内容信息是深度纠缠的。模型根本分不清哪个是要保留的内容,哪个是要去掉的退化,最后要么把退化当成内容生成,出现各种奇怪伪影;要么为了去掉退化,把原图的细节也磨没了。

论文里做了一组关键对比实验,直接把这个问题摆到了台面上:
在这里插入图片描述

图片1 退化信息对生成结果的干扰对比
出处:DiffBIR论文原文Fig.1
分析:第一行是同一张高清图,叠加了不同退化(高斯噪声、散粒噪声、泊松噪声、JPEG压缩噪声)得到的低质图;第二行是直接用这些带退化的低质图当条件,训出来的扩散模型生成结果——能明显看到,不同的退化带来了严重的人脸畸变、颜色偏移和细节错误;第三行是DiffBIR两阶段的结果,无论输入是什么退化,生成结果都稳定、真实,无任何伪影。

基于这个核心痛点,DiffBIR提出了颠覆性的两阶段解耦思路:把BIR问题拆成两个完全独立的子问题,分开优化、无缝配合:

  1. 退化去除阶段:用恢复模块把低质图里的噪声、模糊这些“脏东西”全去掉,拿到一张结构保真、但细节不够丰富的“干净图”;
  2. 信息再生阶段:用生成模块,以干净图为条件,利用预训练扩散模型的强大生成能力,补回丢失的高清细节,完全不受原始退化干扰。

整个框架的整体结构如下:

在这里插入图片描述

图片2 DiffBIR两阶段整体框架图
出处:DiffBIR论文原文Fig.2
分析:整个框架分为两大核心模块:左侧的Restoration Module(RM,恢复模块)和右侧的Generation Module(GM,生成模块)。无论是超分、人脸修复还是去噪任务,只需更换对应任务的RM模块做退化去除,GM模块可完全复用,无需重新训练,这是它能实现统一框架的核心。中间还加入了可选的Restoration Guidance(恢复引导)模块,用户可手动调节“保真度”和“生成质量”的平衡,完全无需重训模型。

二、第一阶段:Restoration Module 退化去除模块——先把图片“洗干净”

RM模块的核心目标非常纯粹:只去退化,不生成新内容,把低质图里和内容无关的退化信息全部抹除,保住原始图像的结构和内容,给第二阶段的生成提供一个“干净、可靠”的条件。

1. 推理时的任务专属RM

由于盲超分、人脸修复、去噪这几个任务的退化类型差异极大,比如去噪要重点处理相机的暗电流噪声、热噪声,人脸修复要聚焦人脸的结构退化,因此DiffBIR没有设计通用RM,而是直接采用对应任务里的SOTA模型作为RM,具体对应关系为:

  • 盲超分任务:采用BSRNet
  • 盲人脸修复:采用DifFace中使用的SwinIR
  • 盲图像去噪:采用SCUNet-PSNR

这个设计的优势极为明显:每个任务的RM都是对应领域经过充分验证的成熟模型,能最大程度去除对应退化;同时整个框架的灵活性拉满,后续出现更优的去退化模型,直接替换RM即可,GM模块完全无需改动。

2. 训练GM时用的预训练RM

论文里有一个非常关键的设计:训练GM的时候,不能直接用原始低质图或任务专属RM的输出当条件,而是单独训练了一个用MSE损失优化的RM,专门用来给GM生成训练用的条件图。

这个RM的优化目标公式如下:
IRM=RM(Ilq),LRM=∥IRM−Ihq∥22I_{RM}=RM\left(I_{lq}\right), \mathcal{L}_{RM}=\left\| I_{RM}-I_{hq}\right\| _{2}^{2}IRM=RM(Ilq),LRM=IRMIhq22
公式中每个符号的通俗解释:

  • IhqI_{hq}Ihq:高清原图(Ground Truth,即最终想要还原的目标图)
  • IlqI_{lq}Ilq:合成的低质图,由高清原图叠加大范围退化生成,用于模拟真实世界的各类图像破坏
  • RM(⋅)RM(\cdot)RM():我们训练的恢复模块,输入为低质图,输出为去退化后的恢复图
  • IRMI_{RM}IRM:RM模块输出的恢复图
  • LRM\mathcal{L}_{RM}LRM:RM模块的损失函数,采用L2损失(均方误差),目标是让恢复图和高清原图的像素值尽可能接近
  • ∥⋅∥22\left\| \cdot \right\| _{2}^{2}22:L2范数的平方,即计算两个图每个像素差值的平方和,用于衡量两个图的像素级相似度

这个设计的核心目的是:这个RM用大范围的退化训练,能生成足够多样化、足够干净的条件图,让GM模块在训练时只需关注“如何根据干净的结构生成真实细节”,完全不用处理退化的干扰,训练出的GM模块稳定性和泛化能力大幅提升。而这个用于生成训练条件的RM,在推理时可直接丢弃,不影响最终使用。

三、第二阶段:Generation Module 细节生成模块——给干净图“补高清buff”

这个模块的核心,是利用预训练Stable Diffusion(SD,潜空间扩散模型,通俗说就是当前AI生成图像最常用的底座大模型,见过海量高清图,具备超强的真实细节生成能力)的生成先验,以第一阶段RM输出的干净图为条件,生成逼真的高清细节。

1. 前置知识:Stable Diffusion的核心公式

Stable Diffusion在潜空间(而非像素空间)完成扩散和去噪,先通过VAE编解码将图片压缩到潜空间,大幅降低计算量。

首先是扩散过程(给潜变量添加噪声的过程)公式:
zt=α‾tz+1−α‾tϵz_{t}=\sqrt{\overline{\alpha}_{t}} z+\sqrt{1-\overline{\alpha}_{t}} \epsilonzt=αt z+1αt ϵ
公式中每个符号的通俗解释:

  • zzz:高清原图经过VAE编码器编码后得到的干净潜变量(可理解为图片在低维空间的“压缩包”,保留了核心内容信息)
  • ttt:扩散的时间步,取值范围从0到T,t越大,添加的噪声越多,潜变量越接近纯高斯噪声
  • α‾t\overline{\alpha}_{t}αt:随时间步变化的累积噪声系数,是提前定义的固定值,t越大,α‾t\overline{\alpha}_{t}αt越小
  • ϵ\epsilonϵ:从标准高斯分布中采样的纯噪声,和zzz的形状完全一致
  • ztz_{t}zt:第t个时间步,给干净潜变量zzz添加对应强度噪声后得到的带噪潜变量

SD的训练目标,是训练一个UNet网络ϵθ\epsilon_{\theta}ϵθ,使其能根据带噪潜变量ztz_tzt、文本条件ccc、时间步ttt,预测出当时添加的噪声ϵ\epsilonϵ,损失函数公式如下:
Lldm=Ez,c,t,ϵ[∥ϵ−ϵθ(α‾tz+1−α‾tϵ,c,t)∥22]\mathcal{L}_{ldm}=\mathbb{E}_{z, c, t, \epsilon}\left[\left\| \epsilon-\epsilon_{\theta}\left(\sqrt{\overline{\alpha}_{t}} z+\sqrt{1-\overline{\alpha}_{t}} \epsilon, c, t\right)\right\| _{2}^{2}\right]Lldm=Ez,c,t,ϵ[ ϵϵθ(αt z+1αt ϵ,c,t) 22]
公式中每个符号的通俗解释:

  • E[⋅]\mathbb{E}[\cdot]E[]:期望,即对所有采样的z,c,t,ϵz,c,t,\epsilonz,c,t,ϵ求平均损失
  • ccc:文本条件,即AI生成图像的提示词,SD通过该条件控制生成内容
  • ϵθ(⋅)\epsilon_{\theta}(\cdot)ϵθ():待训练的UNet噪声预测网络,输入为带噪潜变量、文本条件、时间步,输出为预测的噪声
  • 整个损失的核心目标:让网络预测的噪声,和实际添加的真实噪声尽可能接近。网络预测越准,去噪时就能越精准地移除噪声,还原出干净的潜变量,最终解码出高清图像。

2. 核心创新:IRControlNet

传统的ControlNet直接将条件图(如边缘图、深度图)编码后喂给ControlNet编码器,以此控制SD的生成。但论文中发现,直接用原版ControlNet做图像恢复,会出现严重的颜色偏移,且保真度表现极差,对比效果如下:

在这里插入图片描述

图片3 IRControlNet与原版ControlNet的效果对比
出处:DiffBIR论文原文Fig.9(右)
分析:能明显看到,原版ControlNet的输出出现了严重的颜色偏移,画面偏色失真;而IRControlNet的输出完美保留了原图的颜色,结构和细节也更精准。

论文通过深度消融实验发现,原版ControlNet的核心问题集中在三个方面:条件编码、条件网络的输入、权重初始化。IRControlNet针对这三个问题做了全方面的专属优化,架构如下:

在这里插入图片描述

图片4 IRControlNet架构与4个消融变体的对比
出处:DiffBIR论文原文Fig.3
分析:IRControlNet的架构核心分为三个部分:条件编码、条件网络、特征调制,每一部分都针对图像恢复任务做了专属优化,4个消融变体则用于验证每个部分的有效性。

接下来拆解IRControlNet的三大核心设计:

(1)条件编码:用预训练VAE编码器,把条件图映射到潜空间

原版ControlNet采用从零训练的小卷积网络编码条件图,而IRControlNet直接使用SD中预训练好的、权重固定的VAE编码器ε\varepsilonε,对RM输出的条件图IRMI_{RM}IRM进行编码,公式如下:
cRM=E(IRM)c_{RM}=E(I_{RM})cRM=E(IRM)
公式中每个符号的通俗解释:

  • E(⋅)E(\cdot)E():SD中预训练好的VAE编码器,权重固定不参与训练
  • IRMI_{RM}IRM:第一阶段RM模块输出的干净条件图
  • cRMc_{RM}cRM:条件图经过VAE编码后得到的条件潜变量,和SD的潜变量ztz_tzt处于同一空间

这一步的核心优势:SD的整个去噪过程都在潜空间中完成,将条件图也编码到同一潜空间,能让条件信息和去噪过程完美对齐,从根源上解决了原版ControlNet的颜色偏移问题;同时预训练VAE已在海量图片上学到了超强的图像表征能力,效果远优于从零训练的小网络。论文消融实验证明,这一步直接让PSNR平均提升了3dB,效果提升极为显著。

(2)条件网络:带时间步感知的权重拷贝初始化

IRControlNet的条件网络,直接拷贝SD预训练UNet的编码器和中间块权重,构建可训练的条件分支,这一点和原版ControlNet一致,但有一个核心改进:条件网络的输入,是带噪潜变量ztz_tzt和条件潜变量cRMc_{RM}cRM的通道拼接,公式如下:
zt′=cat(zt,cRM)z_{t}'=cat(z_{t}, c_{RM})zt=cat(zt,cRM)
公式中每个符号的通俗解释:

  • cat(⋅)cat(\cdot)cat():通道维度的拼接操作,将两个形状一致的张量在通道维度合并
  • ztz_tzt:当前时间步的带噪潜变量
  • cRMc_{RM}cRM:条件图编码后的条件潜变量
  • zt′z_{t}'zt:条件网络的最终输入

为什么要把ztz_tzt加入输入?论文消融实验发现,若只输入cRMc_{RM}cRM,模型收敛速度会显著变慢,且生成的图像过于平滑,缺乏足够的纹理细节。因为ztz_tzt包含了当前时间步的噪声信息,将其喂给条件网络,能让条件网络感知当前的去噪进度,从而输出更精准的控制信号,既加快了模型收敛,又提升了生成细节的质量。

同时,条件网络采用预训练UNet的权重初始化,而非从零训练,这一点也至关重要。消融实验中,从零初始化的变体3,所有指标均为最差,且训练无法收敛——因为预训练权重已包含海量的图像生成知识,用其初始化能让条件网络快速学会向SD输出有效的控制信号。

(3)特征调制:跳层连接的零卷积控制

IRControlNet的条件网络会输出多尺度特征,这些特征通过加法操作,调制到SD冻结UNet的对应跳层连接和中间块上;同时在连接位置采用零卷积(权重初始化为0的1×1卷积),保证训练初期的稳定性。

为什么选择跳层连接而非解码器特征?论文对比发现,两者效果接近,但解码器特征的通道数是跳层特征的两倍,会带来额外的参数量和计算量,因此选择跳层连接是性价比最高的方案。

最终,IRControlNet的训练损失函数和SD的训练目标一致,仅新增了条件潜变量cRMc_{RM}cRM作为输入,公式如下:
LGM=Ezt,c,t,ϵ,cRM[∥ϵ−ϵθ(zt,c,t,cRM)∥22]\mathcal{L}_{GM}=\mathbb{E}_{z_{t}, c, t, \epsilon, c_{RM}}\left[\left\| \epsilon-\epsilon_{\theta}\left(z_{t}, c, t, c_{RM}\right)\right\| _{2}^{2}\right]LGM=Ezt,c,t,ϵ,cRM[ϵϵθ(zt,c,t,cRM)22]
公式中每个符号的通俗解释:

  • 所有符号和SD的损失函数完全一致,仅在噪声预测网络ϵθ\epsilon_{\theta}ϵθ的输入中新增了条件潜变量cRMc_{RM}cRM
  • 训练过程中,仅更新IRControlNet的条件网络和特征调制模块的权重,SD的主干UNet和VAE权重全部冻结。这样既能充分利用SD的预训练先验,又不会破坏SD的生成能力,同时大幅降低了训练成本。

四、点睛之笔:Region-Adaptive Restoration Guidance 区域自适应恢复引导

用生成式模型做图像恢复,通常会遇到一个两难问题:想要生成的细节更真实,就容易丢失原图的结构和内容(保真度不足);想要完全还原原图的结构,细节又不够丰富(生成质量不足)。

DiffBIR给出了一个训练-free的解决方案:无需重新训练模型,推理时通过一个可调的引导尺度,就能让用户在保真度和生成质量之间自由切换;同时采用区域自适应设计——平坦区域(如天空、墙面)更侧重保真度,避免生成无关内容;高频区域(如纹理、边缘、五官)更侧重生成质量,补全丰富的细节。

整个引导过程在SD的每一个采样步中执行,核心流程如下:

在这里插入图片描述

图片5 区域自适应恢复引导的整体流程
出处:DiffBIR论文原文Fig.5
分析:在每一个采样步中,UNet先预测出噪声,计算出当前步预测的干净潜变量z‾0\overline{z}_0z0,然后通过区域自适应MSE损失,引导该潜变量向RM输出的高保真图靠拢,最后通过梯度下降更新潜变量,再进入下一个采样步。

接下来拆解该过程的核心公式,每个符号均附带详细解释。

第一步,每个采样步中,先预测当前步的干净潜变量:
ϵt=ϵθ(zt,c,t,cRM),z‾0=zt−1−α‾tϵtα‾t\epsilon_{t}=\epsilon_{\theta}\left(z_{t}, c, t, c_{RM}\right), \overline{z}_{0}=\frac{z_{t}-\sqrt{1-\overline{\alpha}_{t}} \epsilon_{t}}{\sqrt{\overline{\alpha}_{t}}}ϵt=ϵθ(zt,c,t,cRM),z0=αt zt1αt ϵt
公式中每个符号的通俗解释:

  • ϵt\epsilon_{t}ϵt:UNet在第t个时间步预测出的噪声
  • z‾0\overline{z}_{0}z0:根据预测的噪声,反推得到的当前步对应的干净潜变量(即移除当前所有噪声后能得到的潜变量)
  • 其余符号和前文的扩散公式完全一致

第二步,计算区域自适应的权重图。核心思路是:梯度小的平坦区域,赋予更大的权重,使其更贴近高保真图;梯度大的高频区域,赋予更小的权重,保留更多的生成细节。

首先用Sobel算子计算RM输出的高保真图IRMI_{RM}IRM的梯度幅度,然后将图像划分为不重叠的块,计算每个块的梯度幅度G(IRM)G(I_{RM})G(IRM),最终权重图的计算公式为:
W=1−G(IRM)W=1-G(I_{RM})W=1G(IRM)
公式中每个符号的通俗解释:

  • G(IRM)G(I_{RM})G(IRM):每个图像块的梯度幅度,值越大,说明该区域是边缘、纹理等高频区域,细节越丰富
  • WWW:最终的权重图,和输入图尺寸完全一致,每个像素对应一个权重值。平坦区域的GGG值小,因此WWW值大;高频区域的GGG值大,因此WWW值小。

第三步,定义区域自适应MSE损失函数:
L(z~0)=1HWC∥W⊙(D(z~0)−IRM)∥22\mathcal{L}\left(\tilde{z}_{0}\right)=\frac{1}{H W C}\left\| \mathcal{W} \odot\left(\mathcal{D}\left(\tilde{z}_{0}\right)-I_{R M}\right)\right\| _{2}^{2}L(z~0)=HWC1W(D(z~0)IRM)22
公式中每个符号的通俗解释:

  • z~0\tilde{z}_{0}z~0:当前步待优化的干净潜变量
  • H,W,CH,W,CH,W,C:分别为图像的高度、宽度、通道数,用于损失归一化
  • D(⋅)\mathcal{D}(\cdot)D():SD中预训练的VAE解码器,用于将潜变量解码回像素空间的图像
  • ⊙\odot:哈达玛积,即两个矩阵对应位置的元素直接相乘,这里用于给每个像素的差值乘上对应位置的权重WWW
  • 整个损失的核心目标:让解码后的图像,与高保真的IRMI_{RM}IRM的加权差值尽可能小。平坦区域权重高,对损失的贡献大,因此会更贴近IRMI_{RM}IRM;高频区域权重低,对损失的贡献小,因此能保留更多的生成细节。

第四步,用梯度下降更新潜变量,公式如下:
z~0′=z~0−s∇z~0L(z~0)\tilde{z}_{0}'=\tilde{z}_{0}-s \nabla_{\tilde{z}_{0}} \mathcal{L}\left(\tilde{z}_{0}\right)z~0=z~0sz~0L(z~0)
公式中每个符号的通俗解释:

  • sss:引导尺度,用户可手动调节的超参数。sss越大,引导强度越高,结果越贴近原图,保真度越高;sss越小,引导强度越低,生成的细节越丰富,视觉质量越高
  • ∇z~0L(z~0)\nabla_{\tilde{z}_{0}} \mathcal{L}\left(\tilde{z}_{0}\right)z~0L(z~0):损失函数对潜变量z~0\tilde{z}_{0}z~0的梯度
  • z~0′\tilde{z}_{0}'z~0:更新后的潜变量,将作为当前步的最终潜变量,进入下一个采样步的去噪过程

这个设计的核心优势在于:完全训练-free,无需修改模型、无需重新训练,推理时仅调节一个参数就能实现效果的平滑过渡;同时区域自适应的设计,完美解决了“平坦区保保真、高频区出细节”的核心需求,这也是DiffBIR在真实场景中实用性拉满的关键原因。

五、实验结果全解析:三大任务全SOTA,消融实验验证核心设计

论文中完成了极其全面的实验,覆盖盲超分(BSR)、盲人脸修复(BFR)、盲图像去噪(BID)三大核心任务,既有合成数据集的定量测试,也有真实世界数据集的定性+定量测试,同时通过全面的消融实验验证了每个模块的有效性。

实验基础设置说明:

  • 训练数据:过滤后的laion2b-en数据集,约1500万张高清图,训练时随机裁剪为512×512分辨率
  • 模型底座:采用Stable Diffusion 2.1-base作为生成先验
  • 训练细节:RM模块训练15万次迭代,IRControlNet训练8万次迭代,推理时采用50步DDPM采样
  • 评价指标:
    • 有参考指标:PSNR(峰值信噪比,越高说明像素级越接近原图,保真度越高)、SSIM(结构相似性,越高说明结构越接近原图)、LPIPS(学习感知图像块相似度,越低说明视觉上越接近原图)、FID(弗雷歇 inception 距离,越低说明生成的图和真实图的分布越接近,真实感越强)
    • 无参考IQA指标:MANIQA、MUSIQ、CLIP-IQA,数值越高说明图像的视觉质量越好,越符合人眼审美

1. 盲图像超分(BSR)任务实验结果

首先是合成数据集DIV2K-Val上的定量结果:

表格1 盲超分任务在DIV2K-Val合成数据集上的定量对比
出处:DiffBIR论文原文Table 2

Metrics FeMaSR DASR Real-ESRGAN+ BSRGAN SwinIR-GAN StableSR PASD DiffBIR (s=0) DiffBIR (s=0.5) DiffBIR (s=1)
PSNR↑ 20.1303 21.2141 21.0348 21.4531 20.7488 21.2392 20.7838 20.5824 21.5808 21.9154
SSIM↑ 0.4451 0.4773 0.4899 0.4814 0.4844 0.4790 0.4727 0.4277 0.4794 0.4986
LPIPS↓ 0.3971 0.4479 0.3921 0.4095 0.3907 0.3993 0.4353 0.3939 0.3935 0.4263
MUSIQ↑ 62.7855 58.1591 64.6389 62.9271 65.4945 57.8069 63.8094 73.1019 68.6657 61.1476
MANIQA↑ 0.1443 0.1531 0.2238 0.1833 0.2061 0.1648 0.2354 0.3836 0.3146 0.2466
CLIP-IQA↑ 0.5674 0.5571 0.5905 0.5195 0.5779 0.5541 0.6125 0.7656 0.7158 0.6347

表格分析:

  • 当引导尺度s=1时,DiffBIR的PSNR和SSIM直接登顶,为所有方法中的最高值,说明其保真度拉满,能完美还原原图的像素和结构;
  • 当引导尺度s=0时,DiffBIR的MUSIQ、MANIQA、CLIP-IQA三个无参考质量指标,全部断层式领先,远超第二名,说明其生成视觉质量为所有方法中的最优水平;
  • 当s=0.5时,DiffBIR能在保真度和视觉质量之间取得完美平衡,两个方向的指标均排在前列,完全能满足日常使用的需求。

再看真实世界数据集的定量结果:

表格2 盲超分任务在真实世界数据集上的定量对比
出处:DiffBIR论文原文Table 3

Datasets Metrics FeMaSR DASR Real-ESRGAN+ BSRGAN SwinIR-GAN StableSR PASD DiffBIR (s=0)
RealSRSet MUSIQ↑ 64.6735 59.2695 63.2675 67.6705 64.2512 64.8372 67.4052 69.4208
MANIQA↑ 0.2142 0.1595 0.1963 0.2240 0.2054 0.2083 0.2370 0.3211
CLIP-IQA↑ 0.6879 0.5236 0.5772 0.6456 0.6008 0.6418 0.6761 0.7637
real47 MUSIQ↑ 68.9384 62.2026 68.1098 69.4741 68.8467 68.3422 70.9712 73.1397
MANIQA↑ 0.2347 0.1454 0.2055 0.2063 0.2217 0.2264 0.2607 0.3682
CLIP-IQA↑ 0.6911 0.5445 0.6382 0.6111 0.6246 0.6574 0.6913 0.7781

表格分析:在两个真实世界的盲超分数据集上,DiffBIR(s=0)的所有指标全部断层式第一,远超Real-ESRGAN、StableSR这些主流方法,说明其在真实世界的复杂退化场景中,泛化能力极强,能处理各类未知退化的低质图,这也是其在开源社区爆火的核心原因。

真实场景的定性效果对比如下:
在这里插入图片描述

图片6 盲超分任务在真实世界数据集上的视觉效果对比
出处:DiffBIR论文原文Fig.6
分析:能明显看到,GAN-based的方法(Real-ESRGAN+、SwinIR-GAN)的输出均过度平滑,细节糊成一团;其他扩散方法的输出,细节要么不真实,要么结构错误;只有DiffBIR的输出,既还原了精准的结构,又生成了极其真实、丰富的细节,比如动物的胡须、花朵的花蕊、文字的边缘,都还原得清晰准确,无任何伪影。

2. 盲人脸修复(BFR)任务实验结果

表格3 盲人脸修复任务在真实世界数据集上的定量对比
出处:DiffBIR论文原文Table 4

Datasets Metrics CodeFormer DifFace VQFR PGDiff DiffBIR (s=0)
LFW-Test FID↓ 40.9065 38.1675 40.2700 35.8094 30.1202
CLIP-IQA↑ 0.6384 0.6335 0.5821 0.7069 0.8085
MANIQA↑ 0.2971 0.2973 0.2830 0.3060 0.4443
Wider-Test FID↓ 41.1986 39.2517 41.3247 41.5814 28.3617
CLIP-IQA↑ 0.6890 0.6467 0.6266 0.7099 0.7948
MANIQA↑ 0.3188 0.2613 0.2790 0.3280 0.4499

表格分析:这里有一个极具说服力的点——DiffBIR的GM模块完全没有在人脸数据集上做过微调,仅更换了人脸修复的RM模块,就直接在LFW-Test和Wider-Test两个经典人脸修复数据集上,拿到了最低的FID、最高的CLIP-IQA和MANIQA,远超CodeFormer、DifFace这些专门做人脸修复的SOTA方法。这直接证明了DiffBIR框架的超强泛化能力和通用性,更换RM即可适配完全不同的任务,无需重新训练生成模块。

人脸修复的定性效果对比如下:
在这里插入图片描述

图片7 盲人脸修复任务在真实世界数据集上的视觉效果对比
出处:DiffBIR论文原文Fig.7
分析:其他专门做人脸修复的方法,要么把人脸旁边的手修变形,要么侧脸的五官、牙齿、下巴完全修错,因为它们的人脸先验过强,仅能生成正脸,遇到特殊角度就会翻车;而DiffBIR不仅完美还原了人脸的五官和细节,连旁边的手、侧脸的轮廓都修得精准无误,无任何变形,这就是通用生成先验的核心优势。

3. 盲图像去噪(BID)任务实验结果

表格4 盲图像去噪任务在真实世界数据集上的定量对比
出处:DiffBIR论文原文Table 5

Methods MUSIQ↑ MANIQA↑ CLIP-IQA↑
CBDNet 48.1149 0.1103 0.4709
DeamNet 45.9949 0.0949 0.4391
Restormer 47.4605 0.0927 0.3857
SwinIR 55.0493 0.1595 0.4130
SCUNet-GAN 58.2170 0.1822 0.5045
DiffBIR (s=0) 69.7278 0.3404 0.7420

表格分析:DiffBIR的所有指标再次断层式领先所有去噪SOTA方法,MUSIQ直接比第二名SCUNet-GAN高出11.5,MANIQA和CLIP-IQA也几乎实现翻倍。

图像去噪的定性效果对比如下:
在这里插入图片描述

图片8 盲图像去噪任务在真实世界数据集上的视觉效果对比
出处:DiffBIR论文原文Fig.8
分析:其他去噪方法,要么把噪声去除的同时磨掉了所有细节,画面过度平滑;要么去噪不彻底,存在残留噪点;只有DiffBIR,既完全去除了所有噪点,又完美还原了画面中的纹理和细节,画面干净又真实,无任何过度平滑的问题。

4. 关键消融实验

论文中完成了全面的消融实验,验证了每个核心设计的有效性,这里选取最关键的两组。

第一组,两阶段设计的有效性,即RM模块的核心作用:

表格5 RM模块的消融实验结果
出处:DiffBIR论文原文Table 6

Datasets Metrics w/o RM w/ RM
RealSRSet MANIQA↑ 0.2386 0.2477
MUSIQ↑ 62.5683 64.7319
CLIP-IQA↑ 0.6818 0.7075
ImageNet-Val-1k PSNR↑ 22.8481 23.0078
SSIM↑ 0.5039 0.5198
LPIPS↓ 0.4076 0.4026

表格分析:移除RM模块,直接用低质图当条件训练模型,所有指标全面下降,视觉效果上会出现严重的结构失真和伪影,直接证明了两阶段解耦设计的核心作用——先去退化,再补细节,从根源上避免了退化信息对生成过程的干扰。

第二组,IRControlNet和原版ControlNet的效果对比:

表格6 IRControlNet与原版ControlNet的PSNR对比
出处:DiffBIR论文原文Table 7

Set14 BSD100 manga109 ImageNet-Val-1k
w/ ControlNet 20.9435 22.4923 20.2692 22.2874
w/ IRControlNet 23.5193 23.8778 23.2439 24.2534

表格分析:IRControlNet在所有数据集上,PSNR均比原版ControlNet高出2dB以上,效果提升极为显著,直接证明了IRControlNet的三个核心设计,完美适配了图像恢复任务的需求。

六、核心代码实现

这里给出DiffBIR两个核心模块的PyTorch实现:IRControlNet的核心架构,以及区域自适应恢复引导的核心逻辑。

1. IRControlNet核心模块实现

import torch
import torch.nn as nn
from diffusers import StableDiffusionPipeline, UNet2DConditionModel, AutoencoderKL

class IRControlNet(nn.Module):
    def __init__(
        self,
        sd_model_path: str = "stabilityai/stable-diffusion-2-1-base",
        conditioning_channels: int = 4,  # VAE编码后的潜变量通道数
    ):
        super().__init__()
        # 加载预训练SD的VAE,权重固定
        self.vae = AutoencoderKL.from_pretrained(sd_model_path, subfolder="vae")
        for param in self.vae.parameters():
            param.requires_grad = False
        
        # 加载预训练SD的UNet,主干权重固定
        self.unet = UNet2DConditionModel.from_pretrained(sd_model_path, subfolder="unet")
        for param in self.unet.parameters():
            param.requires_grad = False
        
        # 拷贝UNet的编码器和中间块,构建ControlNet条件分支
        self.control_encoder = self._copy_unet_encoder()
        # 零卷积层,用于特征调制,权重初始化为0
        self.zero_convs = self._build_zero_convs()
        
        # 输入层,处理拼接后的带噪潜变量+条件潜变量
        self.conv_in = nn.Conv2d(
            in_channels=conditioning_channels * 2,  # z_t(4) + c_RM(4) = 8通道
            out_channels=self.unet.conv_in.out_channels,
            kernel_size=self.unet.conv_in.kernel_size,
            padding=self.unet.conv_in.padding
        )
        # 输入层权重初始化为0,保证训练初期稳定
        nn.init.zeros_(self.conv_in.weight)
        nn.init.zeros_(self.conv_in.bias)

    def _copy_unet_encoder(self):
        """拷贝UNet的编码器和中间块,初始化权重"""
        control_encoder = nn.ModuleList()
        # 拷贝down_blocks
        for down_block in self.unet.down_blocks:
            control_encoder.append(type(down_block)(**down_block.config))
        # 拷贝mid_block
        control_encoder.append(type(self.unet.mid_block)(**self.unet.mid_block.config))
        
        # 加载预训练权重
        for i, down_block in enumerate(self.unet.down_blocks):
            control_encoder[i].load_state_dict(down_block.state_dict())
        control_encoder[-1].load_state_dict(self.unet.mid_block.state_dict())
        
        return control_encoder

    def _build_zero_convs(self):
        """构建零卷积层,用于连接ControlNet和UNet主干"""
        zero_convs = nn.ModuleList()
        # down_blocks对应的零卷积
        for down_block in self.unet.down_blocks:
            out_channels = down_block.resnets[-1].out_channels
            zero_convs.append(nn.Conv2d(out_channels, out_channels, kernel_size=1, padding=0))
        # mid_block对应的零卷积
        mid_out_channels = self.unet.mid_block.resnets[-1].out_channels
        zero_convs.append(nn.Conv2d(mid_out_channels, mid_out_channels, kernel_size=1, padding=0))
        
        # 所有权重初始化为0
        for conv in zero_convs:
            nn.init.zeros_(conv.weight)
            nn.init.zeros_(conv.bias)
        
        return zero_convs

    def encode_condition(self, condition_image: torch.Tensor) -> torch.Tensor:
        """用VAE编码条件图像,得到条件潜变量c_RM"""
        # VAE的输入需要归一化到[-1, 1]
        condition_image = condition_image * 2.0 - 1.0
        # 编码,缩放因子0.18215是SD固定的
        with torch.no_grad():
            latent = self.vae.encode(condition_image).latent_dist.sample()
            latent = latent * self.vae.config.scaling_factor
        return latent

    def forward(
        self,
        noisy_latent: torch.Tensor,  # z_t,带噪潜变量
        timestep: torch.Tensor,       # 时间步t
        encoder_hidden_states: torch.Tensor,  # 文本条件c
        condition_image: torch.Tensor,        # 条件图像I_RM
    ):
        # 1. 编码条件图像,得到条件潜变量c_RM
        condition_latent = self.encode_condition(condition_image)
        # 2. 拼接带噪潜变量和条件潜变量,得到条件网络输入
        control_input = torch.cat([noisy_latent, condition_latent], dim=1)
        # 3. 输入卷积层
        x = self.conv_in(control_input)
        
        # 4. 条件编码器前向传播,保存多尺度控制特征
        control_features = []
        # down_blocks前向
        for down_block in self.control_encoder[:-1]:
            x = down_block(x, timestep, encoder_hidden_states)
            control_features.append(x)
        # mid_block前向
        x = self.control_encoder[-1](x, timestep, encoder_hidden_states)
        control_features.append(x)
        
        # 5. 零卷积处理控制特征
        control_features = [zero_conv(feat) for zero_conv, feat in zip(self.zero_convs, control_features)]
        
        # 6. 把控制特征注入UNet主干,得到最终噪声预测
        unet_out = self.unet(
            noisy_latent,
            timestep,
            encoder_hidden_states=encoder_hidden_states,
            down_block_additional_residuals=control_features[:-1],
            mid_block_additional_residual=control_features[-1]
        )
        
        return unet_out.sample

2. 区域自适应恢复引导核心逻辑实现

import torch
import torch.nn.functional as F
from kornia.filters import Sobel
from diffusers import AutoencoderKL

def region_adaptive_guidance(
    latent: torch.Tensor,          # 当前步的潜变量z0
    vae: AutoencoderKL,             # SD的VAE解码器
    guidance_image: torch.Tensor,   # RM输出的高保真引导图I_RM
    guidance_scale: float = 1.0,    # 引导尺度s
):
    """
    区域自适应恢复引导的核心实现,单步梯度下降更新潜变量
    """
    # 开启梯度计算
    latent = latent.detach().clone().requires_grad_(True)
    # 1. 把潜变量解码回像素空间
    latent_denorm = latent / vae.config.scaling_factor
    decoded_image = vae.decode(latent_denorm).sample
    # 把解码后的图像归一化到[0,1],和引导图对齐
    decoded_image = (decoded_image + 1.0) / 2.0
    decoded_image = torch.clamp(decoded_image, 0.0, 1.0)
    
    # 2. 计算引导图的梯度幅度,生成权重图W
    sobel = Sobel()
    # 计算引导图的梯度幅度
    grad_magnitude = sobel(guidance_image)
    # 分块计算平均梯度幅度,和论文保持一致采用8x8块
    kernel_size = 8
    patch_grad = F.avg_pool2d(grad_magnitude, kernel_size=kernel_size, stride=kernel_size)
    # 上采样回原图尺寸
    patch_grad = F.interpolate(patch_grad, size=guidance_image.shape[2:], mode="nearest")
    # 归一化到[0,1]
    patch_grad = (patch_grad - patch_grad.min()) / (patch_grad.max() - patch_grad.min() + 1e-8)
    # 计算权重图W=1-G
    weight_map = 1.0 - patch_grad
    
    # 3. 计算区域自适应MSE损失
    loss = torch.mean(weight_map * (decoded_image - guidance_image) ** 2)
    
    # 4. 梯度下降更新潜变量
    loss.backward()
    updated_latent = latent - guidance_scale * latent.grad
    updated_latent = updated_latent.detach()
    
    return updated_latent

七、总结与局限

核心总结

DiffBIR的核心贡献,可总结为三点:

  1. 首次提出了两阶段解耦的统一盲图像恢复框架,把BIR任务拆成“退化去除”和“信息再生”两个独立阶段,完美解决了退化信息干扰生成过程的核心痛点,一套框架搞定盲超分、人脸修复、图像去噪三大核心任务,全部实现SOTA效果。
  2. 提出了IRControlNet,针对图像恢复任务优化了条件编码、条件网络和特征调制,完美适配潜空间扩散模型,从根源上解决了原版ControlNet的颜色偏移、保真度不足的问题,大幅提升了生成效果和训练稳定性。
  3. 设计了训练-free的区域自适应恢复引导,推理时仅通过一个可调参数,就能实现保真度和生成质量的平滑过渡;同时区域自适应的设计,完美平衡了平坦区的保真度和高频区的细节生成,极大提升了真实场景的实用性。

论文中提到的局限

  1. 推理速度仍有提升空间:DiffBIR默认需要50步采样才能得到最优效果,相比GAN-based的单步方法,计算成本更高,推理速度更慢。不过后续已有大量工作基于DiffBIR做了采样加速,比如通过知识蒸馏将采样步数压缩到几步甚至单步。
  2. 两阶段的设计未来可拓展到更多盲图像恢复任务,比如去模糊、去雨、去雾、老照片修复等,只需替换对应的RM模块,即可快速适配新任务。

DiffBIR能在开源社区爆火,核心原因在于:它不仅在学术上把统一盲图像恢复的框架做到了极致,更在工程上提供了极其灵活、易用、效果拉满的解决方案,无论是学术研究还是工业落地,都具备极高的参考价值。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐