资讯动态

RetinexNet夜间图像增强:从Retinex原理到PyTorch工程实践

发布时间:2026/9/13 5:41:09 来源:尧图企业网站定制
简介RetinexNet-master是基于Retinex理论的深度学习夜间图像增强项目面向图像处理研究者和开发者重点解决低照度环境下图像对比度不足、噪声明显、细节丢失等问题。项目结合多尺度Retinex思想将图像分解为照明与反射分量分别处理并通过深度网络学习不同光照条件特征在提升对比度的同时保持自然观感适用于监控、自动驾驶、无人机摄影等夜间视觉场景。压缩包共20个文件大小约11.65MB涵盖Python源码、模型权重checkpoint/meta/index/data、示例图片及说明文档结构清晰便于直接运行或二次开发。目前已有576人学习下载适合想快速上手夜间图像增强算法、了解模型训练与推理流程的研究者。开发者可通过源码理解核心原理借助预训练权重在自有数据上测试效果为后续改进与落地提供起点。1. RetinexNet 把夜间图像增强拆成两个子问题夜间拍照最大的问题不是“暗”而是暗部细节和亮部细节压在一起直方图均衡、Gamma 校正这类图像增强算法把暗部提亮时会把噪点也带出来整体画面发灰。RetinexNet-master 这套代码核心不是直接提亮度而是先用一个分解网络把输入图像拆成反射图reflectance和照度图illumination反射图代表物体原本的颜色和纹理照度图代表光照分布。然后只对照度图做对比度增强再把两张图乘回去暗部亮度提上来了颜色和细节也不会跟着噪声一起崩。RetinexNet 是 2018 年 BMVC 上提出的一种深度 Retinex 分解方法网络结构不复杂训练数据也不需要太大规模。做夜间监控、手机夜景模式、低光照目标检测的工程师都可以拿它当增强管线里的第一级。对熟手来说它最大的价值是给图像增强提供了一个可解释的中间表示你能清楚看到网络到底改了哪个分量。下面按“原理拆解 → 最小实现 → 参数调优 → 落地验证”的顺序把这条管线完整过一遍。2. 夜间图像增强Retinex 原理与 RetinexNet 的网络结构2.1 从 Retinex 假设到神经网络为什么不用传统迭代Retinex 理论的核心假设是传感器接收到的图像 S 可以由反射图 R 和照度图 I 逐元素相乘得到即 S R * I。在 log 域里乘法变成加法log(S) log(R) log(I)。反射图表示场景本身的物理属性照度图表示入射光的空间分布。这个假设把“图像增强”从像素级操作变成了两个子问题估计照度、恢复反射。传统单尺度 RetinexSSR用高斯卷积核对原图做平滑来估计照度然后在 log 域里做差得到反射图。多尺度 RetinexMSR再把多个不同尺度的高斯核结果加权融合。问题随之而来高斯核是固定形状的遇到高对比边缘时会把边缘误判成光照突变于是边缘周围出现光晕同时反射图被过度压缩颜色发灰。RetinexNet 换了一条路不预先假设照度一定是平滑的而是用卷积网络直接从图像学习到R, I的映射。照度图可以保留真实光照在物体边界处的断裂反射图也能保留细节两个分量的特性由训练数据决定不再由高斯窗口决定。这就是深度 Retinex 和传统迭代解法最根本的差别也是夜间图像增强这类任务在工程上更倾向于用网络的原因。2.2 分解网络不下采样保边缘是硬要求RetinexNet 的分解网络Decom-Net是一个不包含任何下采样操作的全卷积网络。输入单通道灰度图经过三到四层 3×3 卷积通道数由 1 扩到 32 再到 64最后分成两个分支各自接一层 3×3 卷积输出反射图和照度图。输出用 Sigmoid 约束到 [0,1]保证反射率不会出现负值照度不会出现负光强。不下采样这个设计值得单独说。夜间增强最怕边缘糊如果中间加了 MaxPooling 或者步长为 2 的卷积边缘位置会丢失空间对应关系照度图会把窗帘褶皱、衣服纹理错误地当成光照变化。保持全分辨率意味着显存占用会比普通分类网络高但换来的是分解结果的空间一致性。实际落地时如果显存吃紧优先减小 batch size而不是在网络上加池化。2.3 增强网络和重建一致损失的关系分解完成之后图像被分成了低频的照度图和包含高频细节的反射图。对夜间图像来说照度图需要做亮度拉升和对比度拉伸反射图需要去噪。RetinexNet 原文的处理方式是反射图先用 BM3D 做一步传统去噪照度图再做多尺度增强最后重新相乘得到增强结果。训练时有一条关键约束把增强后的 S_enhanced 再次送入分解网络重新分解出的R, I必须和增强前的R, I保持一致性。这个约束对应的是重建损失和互一致性损失它让网络学到的不是简单变亮而是“变亮之后依然能被稳定地分解”。有了这一项增强结果不容易出现色偏暗部细节也不会被过度涂抹。2.4 训练数据准备伪正常光图怎么构造RetinexNet 的训练需要成对数据同一场景的低光图和正常光图。公开的 LOL 数据集可以直接拿到包含室内外接近 500 对图像。如果实际部署场景和 LOL 差别较大更可靠的办法是自采固定机位用不同曝光参数拍摄同一场景短曝光图作为低光输入。这里要提醒一点低光图不能直接线性缩放否则阴影层次会被压平。只有单张低光图时常见做法是用 Gamma 校正先做一次伪增强配合去噪后当作正常光图来训练。一个简短的预处理示例import cv2 import numpy as np low_img cv2.imread(night.png) # Gamma 系数小于 1暗部提亮同时保留高光比例 enhanced np.power(low_img.astype(np.float32) / 255.0, 0.4) enhanced np.uint8(np.clip(enhanced * 255, 0, 255)) cv2.imwrite(pseudo_normal.png, enhanced)这里的 0.4 是折中值Gamma 越大提亮越猛但超过 0.6 之后阴影层次会被压缩网络学到的是无脑拉升而不是基于 Retinex 分解的增强。3. 用 PyTorch 跑通 RetinexNet 的最小对比度增强代码3.1 分解网络的最简实现先写一个可独立运行的 Decom-Net输入单通道图像输出反射图和照度图import torch import torch.nn as nn class DecomNet(nn.Module): def __init__(self, channel64, kernel_size3): super().__init__() # 输入 1 通道扩展为 channel 维特征 self.conv1 nn.Conv2d(1, channel, kernel_size, padding1, biasFalse) self.conv2 nn.Conv2d(channel, channel, kernel_size, padding1, biasFalse) self.conv3 nn.Conv2d(channel, channel // 2, kernel_size, padding1, biasFalse) self.conv4 nn.Conv2d(channel // 2, channel // 2, kernel_size, padding1, biasFalse) # 反射图和照度图各自独立的输出卷积 self.reflect nn.Conv2d(channel // 2, 1, kernel_size, padding1) self.illum nn.Conv2d(channel // 2, 1, kernel_size, padding1) def forward(self, x): x torch.relu(self.conv1(x)) x torch.relu(self.conv2(x)) x torch.relu(self.conv3(x)) x torch.relu(self.conv4(x)) R torch.sigmoid(self.reflect(x)) I torch.sigmoid(self.illum(x)) return R, I前向里 Sigmoid 把两个输出压到 [0,1]。R 接近 1 表示该像素反射率高I 接近 0 则说明该区域光照很弱。两个分支共享前面的特征提取层但各自有独立卷积头这样训练时反射图关注纹理照度图关注光照分布互不干扰。biasFalse 是为了让卷积归一化更好配合如果你后续要加 BatchNorm保持默认即可。3.2 损失函数重建、互一致、平滑三项组合RetinexNet 的完整训练损失由三部分组成下面给出可以直接抄走的 PyTorch 实现def illum_smooth_loss(I, eps1e-4): # 照度图横向和纵向差分平滑项约束其梯度 dx I[:, :, :, :-1] - I[:, :, :, 1:] dy I[:, :, :-1, :] - I[:, :, 1:, :] return torch.mean(torch.abs(dx)) torch.mean(torch.abs(dy)) def compute_loss(R_low, I_low, S_low, R_high, I_high, S_high): # 重建损失分解结果相乘要能还原回原图 recon_low torch.mean(torch.abs(R_low * I_low - S_low)) recon_high torch.mean(torch.abs(R_high * I_high - S_high)) # 互一致性损失低光和正常光的反射图应趋于一致 consistency torch.mean(torch.abs(R_low - R_high.detach())) \ torch.mean(torch.abs(I_low - I_high.detach())) # 平滑损失照度图本身应该是低频平滑的 smooth illum_smooth_loss(I_low) illum_smooth_loss(I_high) return recon_low recon_high 0.01 * consistency 0.15 * smooth参数说明recon_low 和 recon_high 权重为 1.0是主损失consistency 用 detach 阻断梯度回传到另一张图避免低光和正常光两个分支相互拉扯smooth 权重 0.15太低会导致照度图携带纹理太高会把阴影边界洗掉。夜间监控场景下smooth 权重可以适当提高到 0.2因为监控画面里墙体、路面的大面积均匀区域更需要稳定的亮度过渡。3.3 训练循环和数据预处理训练循环本身不复杂重点在数据接口的处理。RetinexNet 原实现把输入转成灰度图颜色信息不敏感实际落地时更推荐转成 YUV 空间只对 Y 亮度通道做 Retinex 增强UV 通道保持原样。原因是夜间图像暗部色度噪声很大增强 RGB 三个通道会导致三个通道的噪声被同时放大最终表现为彩色噪点。optimizer torch.optim.Adam(model.parameters(), lr1e-4) for epoch in range(50): for low_batch, high_batch in dataloader: low_batch low_batch.to(device) high_batch high_batch.to(device) R_low, I_low model(low_batch) R_high, I_high model(high_batch) loss compute_loss(R_low, I_low, low_batch, R_high, I_high, high_batch) optimizer.zero_grad() loss.backward() optimizer.step()学习率 1e-4 起步每 20 轮衰减一半。因为分解网络全分辨率前向batch size 压到 8 到 16 比较稳妥50 到 100 轮就能看到稳定的提亮效果并不需要训练几百轮。数据增强方面随机裁剪 128×128 或 256×256 小块就够旋转和翻转要慎用——夜间图像有明确的方向性翻转之后路灯和天空的位置关系会破坏分解的一致性。3.4 推理流程先提亮照度图再乘回反射图推理阶段有两个容易踩的坑。第一个是输入要归一化到 [0,1] 而不是 [0,255]第二个是输出图像里会有少量像素越界必须 clip。最简单的对照度图的增强操作是幂律变换I_enhanced I_low ** 0.5系数小于 1 时暗部被提亮。再把去噪后的反射图乘回去R, I model(low_tensor) I_enhanced torch.pow(I, 0.5) result R * I_enhanced result torch.clamp(result, 0.0, 1.0)注意如果只追求暗部更亮可以在 I_enhanced 上继续叠加线性拉伸但拉伸幅度过大会把高光区域一起提爆路灯、车灯周围会出现一圈白色光晕。4. 训练与落地RetinexNet 的关键参数与暗部偏色坑4.1 5 个必调参数学习率、损失权重、批大小、迭代数和 GammaRetinexNet 跑通容易跑稳需要调参。下面这张表是我在实际项目里常用的参数起点参数推荐值作用调参方向学习率1e-4控制反射图和照度图的收敛速度暗部提亮不足时降到 5e-5互一致性损失权重0.01约束两个曝光分支的分解一致性反射图携带光照信息时上调到 0.05照度平滑损失权重0.1 ~ 0.2控制照度图的低频程度光晕严重时上调细节丢失时下调batch size8 ~ 16影响梯度稳定性和显存占用梯度震荡时加大到 32推理 Gamma0.4 ~ 0.6对照度图做非线性拉伸整体偏暗下调过曝上调注意单张图做伪训练对时Gamma 超过 0.6网络学到的实际上是直方图拉伸而不是 Retinex 分解暗部层次会明显丢失。4.2 暗部偏色和光晕从哪里来夜间图像增强最常见的问题集中在两类偏色和光晕。偏色的源头在反射图。暗部区域信噪比低网络分不清真实纹理和传感器噪声当反射图在噪声处出现不稳定的高低跳变颜色就跟着偏。处理手段不是直接调损失权重而是在训练前对低光图做一次引导滤波把传感器热噪声先压掉一部分。光晕则出在照度图。当平滑损失权重偏低照度图会保留高对比边缘的梯度放大后的结果在路灯、月亮边缘出现一圈暗边。这时候先检查平滑损失的梯度数值如果 I 的梯度集中在少数高对比位置就把 smooth 权重加大或者在损失里加入对角方向的差分def illum_smooth_diag(I): dx torch.abs(I[:, :, :, :-1] - I[:, :, :, 1:]) dy torch.abs(I[:, :, :-1, :] - I[:, :, 1:, :]) dxy torch.abs(I[:, :, :-1, :-1] - I[:, :, 1:, 1:]) return torch.mean(dx) torch.mean(dy) torch.mean(dxy)加入对角差分之后照度图会收敛得更平滑适合室外监控这类大面积平坦区域多的场景。4.3 评估指标SSIM 和 PSNR 之外看什么夜间增强的评估不能只看 SSIM 和 PSNR。这两个指标衡量的是像素级逼近程度而夜间增强的目标是让暗部可辨识、色彩不偏、噪声可控。工程上更有效的指标是暗部区域梯度能量和检测 mAP。计算方式很简单把增强图像按亮度分成多个区间单独统计最低亮度区间里的梯度幅度均值。这个值上升说明新的细节被真正恢复出来而不是单纯把像素值抬高。如果是为了对接目标检测直接对比增强前后的 mAP 更直观。很多情况下 PSNR 下降但 mAP 上升说明图像在像素层面偏离了真实光照但语义信息更清晰了。这时候优先采信 mAP。5. 从 RetinexNet 到夜间图像增强落地小波降噪、多尺度融合与验证5.1 用 Python 小波变换先降噪再交给 RetinexNetRetinexNet 在暗部放大的不只是亮度还有噪声。反射图里的高频噪声会在增强后被同步放大收尾阶段用小波变换做一次软阈值处理是很常用的图像增强算法组合。PyWavelets 可以干净地完成这一步import pywt import numpy as np def wavelet_dn(r, threshold0.03): # 2 层 db4 小波分解 coeffs pywt.wavedec2(r, db4, level2) # 保留近似系数对细节系数做硬阈值收缩 coeffs_n [coeffs[0]] for detail in coeffs[1:]: coeffs_n.append( tuple(np.maximum(np.abs(c) - threshold, 0) * np.sign(c) for c in detail) ) return pywt.waverec2(coeffs_n, db4)硬阈值收缩比软阈值更容易保留边缘锐度但 threshold 不能开太大0.03 起步。阈值太高车轮辐条、树叶缝隙这类真实高频细节会被一起抹掉产生水彩涂层感。当天晚上反射图噪声大时先对反射图做一步引导滤波再做小波变换效果比直接调 threshold 更稳。5.2 三个落地实践多尺度融合、固定机位校准、检测任务对接实践一是多尺度融合。直接增强整张 1080P 夜景图天空和光源区域容易过曝。常见做法是把输入缩放到 0.5 倍和 1.5 倍分别增强再用拉普拉斯金字塔融合取各尺度下细节保留最完整的部分。这个技巧对街景监控特别有用画面里同时存在远处路灯和近处行人单一尺度很难兼顾。实践二是固定机位照明校准。固定摄像头画面里光源位置基本不变可以提前用多张夜间空景图估计一张平均照度先验推理时把 I 的低频分量替换为先验值再与当前帧的反射图相乘。这样做能明显减少画面闪烁同时保持暗区细节稳定。实践三是检测任务对接。增强结果不要直接送进检测模型更好的方式是把原图和增强图做通道维的拼接输入或者在网络浅层做一个多分支融合。检测模型对灰度分布的绝对值并不敏感增加输入多样性比单纯追求视觉效果好得多。5.3 效果验证的一套命令流程最后给出一套可以直接执行的批量验证流程# 批量增强输出到 result 目录 python test_retinex.py --input ./test/low/ --output ./result/enhanced/ # 与正常光参考图对比计算 PSNR / SSIM python eval_ssim.py --gt ./test/high/ --pred ./result/enhanced/ # 统计最低 20% 亮度区域的梯度能量 python eval_gradient.py --pred ./result/enhanced/ --mask ./test/low/ --percentile 0.2eval_gradient.py 里的 percentile 参数表示取全图亮度分布中最低 20% 的区域这个区域的梯度均值对比增强前后必须上升。然后挑几张暗部细节丰富的图放大到 400% 看噪点形态如果反射图里的点状噪声仍然明显把 Gamma 从 0.5 降到 0.45再检查路灯边缘是否出现暗圈。先用小波变换把反射图噪声压住再对增强结果做一次 3×3 中值滤波是收尾阶段最稳的一步。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价