1. 从Retinex理论到SG-LLIE:低光增强的演进之路
大家好,我是老张,一个在图像处理领域摸爬滚打了十多年的工程师。今天想和大家深入聊聊CVPR 2025上备受关注的一个新工作——SG-LLIE低光增强算法。这个算法在NTIRE 2025低光增强挑战赛中拿到了第二名的好成绩,实力不容小觑。很多朋友一听到“Transformer”、“结构引导”这些词可能就有点发怵,觉得太理论、太复杂。别担心,今天我就用最接地气的方式,带大家从最基础的Retinex理论开始,一步步拆解SG-LLIE的整个设计思路和代码实现,保证让你听得懂、学得会。
我们先从最根本的问题说起:为什么低光环境下的照片那么难处理?简单来说,就是光线不足导致相机传感器接收到的信号太弱,图像不仅暗,还充满了噪声和颜色失真。传统的增强方法,比如直接拉高亮度(Gamma校正)或者做直方图均衡,往往会让噪声一起被放大,画面看起来又脏又假。这时候,Retinex理论就登场了。这个理论的核心思想非常直观:它认为我们人眼看到的图像,是由“光照”和“反射”两部分相乘得到的。光照分量代表了环境光的强弱和分布,而反射分量才是物体本身的颜色和纹理。低光增强的目标,其实就是从一张昏暗的输入图像中,尽可能准确地分离并增强反射分量,同时抑制或去除光照不均带来的影响。
SG-LLIE这个名字里的“SG”代表“Structure-Guided”,也就是“结构引导”。这是它最核心的创新点。以往的很多方法,包括一些基于Retinex的深度学习模型,在估计光照和反射分量时,容易过度平滑或者破坏图像的边缘、纹理等结构信息。SG-LLIE聪明地引入了一个“结构先验”来引导整个增强过程。这个先验信息就像一个经验丰富的向导,告诉网络:“这里是物体的边缘,要保护好;这里的纹理很细腻,不要抹平了。” 这样一来,增强后的图像就能在提亮的同时,最大程度地保持清晰度和自然感。它没有直接使用RetinexFormer里的光照引导,而是自己设计了一套全新的结构先验提取机制,并把这个先验作为引导信号,输入到其核心的Transformer模块(论文里叫SGTB,结构引导Transformer块)中,通过内部的交叉注意力机制来指导低光图像的增强,特别关注结构和细节的保持。
2. 核心架构总览:SG-LLIE是如何工作的
在深入代码之前,我们得先对SG-LLIE的整体架构有个宏观的认识。这样再看那些复杂的模块时,你才知道它们各自扮演什么角色,以及是如何串联起来的。整个SG-LLIE的流程可以看作一个“先分析,后增强”的两阶段管道,但它比传统的两阶段方法要精巧和深入得多。
第一阶段:结构先验提取与光照初步估计 算法并不是一上来就直接处理原始的低光图像。它首先会通过一个轻量级的子网络,从输入图像中提取出一个“结构先验图”。这个图可以理解为图像中边缘、轮廓和主要纹理结构的抽象表达。与此同时,另一个并行的分支会进行初步的光照估计,得到一个粗糙的光照图。这个阶段的目标是快速获取图像的全局结构信息和光照分布概况,为后续的精细处理提供关键的引导信号。你可以把这个阶段想象成画家在作画前,先用淡淡的线条勾勒出物体的轮廓和明暗关系,打好底稿。
第二阶段:结构引导的精细化增强 这是算法的核心。初步估计的光照图和提取的结构先验图,会被一起送入一个基于U-Net架构的主干网络中进行精细化处理。这个主干网络就是SG-LLIE的“发动机”。它的编码器-解码器结构能够捕捉图像的多尺度信息。而在这个U-Net的每一层,都嵌入了刚才提到的SGTB(结构引导Transformer块)。SGTB是Transformer架构在图像域的一个巧妙应用。它利用“自注意力”机制让图像各个区域的信息进行全局交互,同时利用“交叉注意力”机制,让当前正在处理的图像特征去“询问”结构先验图:“我这个地方应该增强成什么样?边缘该怎么保持?” 通过这种持续的引导,网络能够在增强亮度、去除噪声的同时,牢牢地“记住”并强化图像原有的结构。
多尺度与渐进式优化 SG-LLIE的U-Net主干和其中的SGTB模块是工作在多个尺度上的。编码器不断下采样,捕捉图像的全局上下文和语义信息;解码器再逐步上采样,恢复细节。这种多尺度设计让算法既能处理大范围的照明变化,又能修复细微的纹理。此外,整个模型往往以“渐进式”的方式堆叠多个阶段,前一个阶段的输出作为后一个阶段的输入,像流水线一样逐步优化图像质量,最终输出清晰、明亮且自然的增强结果。
3. 代码实现深度解析:从模块到网络
看懂了整体框架,我们现在就打开代码,看看这些炫酷的想法是怎么一行行实现的。我会结合论文中的关键模块,用代码片段和通俗解释,带你走一遍核心流程。我们主要关注两个核心文件:RetinexFormer_arch.py(实现核心Transformer块和Retinex流程)和 UHDM_arch.py(实现基于U-Net的主干网络,这里被用作SG-LLIE的骨干)。
3.1 基础构建块:注意力、归一化与卷积
任何复杂的网络都是由基础层堆砌而成的。SG-LLIE也不例外,它复用并定制了一些非常经典且有效的组件。
PreNorm与层归一化 在Transformer里,我们常看到“Pre-Norm”和“Post-Norm”的争论。SG-LLIE采用了PreNorm,也就是在多头自注意力(MSA)或前馈网络(FFN)这些主要计算模块之前进行层归一化(LayerNorm)。我自己的实验经验是,PreNorm通常能让训练更稳定,特别是网络很深的时候,它能缓解梯度消失或爆炸的问题,让你更容易训练出又深又强大的模型。代码里就是一个简单的包装器:
class PreNorm(nn.Module):
def __init__(self, dim, fn): # dim: 特征维度, fn: 要包装的主计算模块
super().__init__()
self.norm = nn.LayerNorm(dim)
self.fn = fn
def forward(self, x, **kwargs):
x = self.norm(x) # 先归一化
return self.fn(x, **kwargs) # 再执行主计算
GELU激活函数 为什么用GELU而不是ReLU?GELU(高斯误差线性单元)是Transformer的标配。你可以把它理解为一个“更平滑的ReLU”。对于负的输入,ReLU直接输出0,而GELU会给予一个很小的、非零的梯度。这种平滑性让模型在训练时更容易优化,能学习到更复杂的模式。它的实现就是简单调用F.gelu(x)。
深度可分离卷积 代码里有一个conv工具函数和大量使用的深度可分离卷积(groups参数等于输入输出通道数)。深度可分离卷积把标准卷积拆成两步:先对每个输入通道单独做空间卷积(深度卷积),再用1x1卷积(逐点卷积)进行通道融合。这样做能大幅减少参数量和计算量,是移动端和高效模型常用的技巧。在SG-LLIE中,它被广泛用于特征提取和变换,既保证了感受野,又控制了模型复杂度。

1369

被折叠的 条评论
为什么被折叠?



