☰
水下图像增强:深度学习与物理模型结合估测透射率
2026/10/14 1:40:32 网站建设 项目流程

研究水下图像增强的人,基本都绕不开同一个开场:水下照片要么偏蓝要么偏绿,再离远一点就开始发糊,像蒙了一层半透明的纱。这个现象不是相机白平衡没调好,而是水体光学特性决定的。光线从场景表面反射回来,在水里走过一段路程后才能到达相机,路径上同时发生吸收和散射:红色波长衰减最快,蓝绿波长穿透力强,再加上水中无处不在的悬浮颗粒散射,最终成像就是典型的"蓝绿色调、低对比度、细节丢失"。这篇《A Deep CNN Method for Underwater Image Enhancement》就是冲着这个退化问题来的,核心思路是用深度CNN估计出透射率图,再结合物理模型把清晰图像反推出来。

整篇论文读下来,最值得琢磨的不是它用了多新的网络结构,而是它对"物理模型+深度学习"这种混合路线的处理方式。论文没有让CNN从头到尾独立完成图片增强,而是把最难的透射率估计交给网络,背景光估计则沿用传统统计方法,再用经典的Jaffe-McGlamery成像模型做图像重建。读之前建议先把水下成像模型和大气去雾的框架过一遍,不然很容易迷失在公式和实验表格里。这篇文章我就按自己的阅读顺序,把论文从问题定义、方法设计、训练数据、实验评估到复现踩坑,一条线串下来讲清楚。

1. 水下图像为什么又蓝又糊:从成像退化说起

下水拍过照的人都有体感:水越深、距离越远,图像糊得越厉害,色彩也越单调。但这只是定性感受,要做算法就必须把退化过程写成数学形式。业内最常用的就是Jaffe-McGlamery水下成像模型,可以写成:

I(x) = J(x)·t(x) + A·(1 - t(x))

这里x是像素坐标,I(x)是相机拍到的退化图像,J(x)是希望恢复的清晰场景辐射,t(x)是透射率图,取值在0到1之间,A是全局背景光。直观理解一下:t(x)越接近1,说明这段光路衰减越少,看到的物体就越清楚;t(x)越接近0,说明物体反光几乎全被水吸收和散射掉了,相机只能拍到背景光。A则是水里远处那层"底色",通常偏蓝偏绿,它不依赖具体物体,相当于一个全局偏置项。

把式子反推一下,就得到图像恢复的核心公式:

J(x) = (I(x) - A) / t(x) + A

看到了吗,只要估计出t(x)和A,理论上就能把清晰图像还原出来。这篇论文的方法本质上是在给这个反推公式补参数,而不是去学一个"退化图直接映射增强图"的黑盒。这个选择在2017年前后有很强的现实意义:真实水下图像很难拿到成对的清晰参考图,端到端模型训练数据不够,容易过拟合,而且出了问题不好解释。物理模型把问题拆解成"估计两个物理量",训练数据也能靠模型反向合成,整个技术路线就闭环了。

不过这里必须强调一点:物理模型给了反推形式,并没有给唯一解。同一个I(x)可以对应很多组不同的(J, t, A)组合,这是一个典型的不适定问题。水下图像增强难,难的不只是怎么算,更在于怎么在无穷多解里找到那个符合真实物理的那一个。后文的CNN方法,本质上是利用大量合成数据在"图像外观—透射率"之间学一个统计优先的映射,把解空间往合理的方向挤。

2. 方法定位:为什么只让CNN学透射率图,不学全部

很多初学者读这篇论文时会有一个疑问:既然物理模型已经给出了公式,直接套暗通道先验估计透射率不就行了,为什么还要引入CNN?答案在于暗通道先验在水下场景经常失效。大气去雾里的暗通道先验假设"无雾清晰图像的局部暗通道趋于零",这个假设在陆地场景大体成立,但水下大片的蓝绿色背景本身就是高亮的,暗通道不再接近零,先验被破坏,估计出的透射率往往偏高,导致恢复图偏暗、偏蓝。

CNN在这里的作用,就是绕开这个脆弱的先验假设,直接学习从图像外观到透射率图的映射。网络输入退化图像,输出对应的透射率图,中间过程完全由数据驱动,不用人手工设计复杂的先验规则。论文很聪明的一点是,没有把增强任务整个交给网络端到端输出J,而是只输出t。这样做的逻辑其实非常工程化:A的估计相对稳定,用传统统计方法就够;t的空间变异性强,和场景深度、水体浓度、光源分布都挂钩,传统方法始终做不干净,这才是数据驱动模型的用武之地。

这个"只学最难子模块"的思路在今天的很多AI系统里其实很常见,用神经网络解决感知或回归问题,用传统算法解决可解释、可验证的部分。论文选择这种混合架构还有一个隐性好处:调试方便。恢复效果一旦不对劲,可以分别检查是t估计错了还是A估计歪了,而不是对着整个黑盒模型无从下手。我在实际复现之后对这个体会特别深——如果端到端模型输出一张偏红的图,你很难定位是解码器哪一层出了问题;但在这套管线里,你只要把中间t图和A打印出来,问题基本就浮出水面了。

2.1 透射率图和背景光的耦合关系

这里要补一个容易忽略的细节。从恢复公式看,A和t在反推过程中是耦合的:A偏大一点,t就得跟着变才能让最终J看起来正常;A偏小,t的估计也会被带偏。换句话说,网络学到的t隐含了训练时A分布的依赖。如果真实测试图像的A估计值和训练数据里的A分布差异很大,网络预测的t就会不准。

论文在合成训练数据时显然考虑到了这点,会对A做一定范围的随机采样,让网络见过更多组合。但考虑到CNN模型并不直接看到A作为输入特征,这种"内化了A的分布"的透射率估计,本质上仍然只是对训练分布的一个插值。这个局限性在后来的很多水下图像增强论文里被反复讨论,也直接启发了"把A也作为网络预测目标"或者"分通道处理不同波长衰减"等改进思路。

3. 网络结构与合成训练数据:值得逐行抠的细节

论文的网络结构单独拎出来看不算惊艳,卷积、池化、全连接、上采样几个模块的组合,在今天已经是基本功。但放在当时,它把"分类网络里耳熟能详的组件"迁移到"单通道透射率回归"上来,本身就是一个很好的示范:深度学习解决问题,不一定要硬造新结构,把一个合适的结构放到合适的问题上同样有效。

3.1 网络结构:从多尺度特征到低分辨率透射率图

网络大致可以分成两段。第一段是常规的卷积特征提取,用若干卷积层加池化层逐步把输入图像压缩成高语义、低空间分辨率的特征图。池化的作用和分类网络一样,是为了扩大感受野。透射率估计特别需要全局视野:图像里一片很暗的区域,可能是远处目标被水严重衰减,也可能是近处遮挡产生的阴影,只看局部很难判断,必须借助更大范围的信息来推断场景深度。

第二段是回归输出部分。这里有一点和后来的主流分割网络不同:它不是全卷积输出逐像素稠密结果,而是把特征压到全连接层,先生成一张低分辨率透射率图,再做上采样放大回输入尺寸。这种做法的优点是输出天然平滑,全连接层很难产生逐像素激烈跳变的噪声图,对透射率这种低频物理量来说是好事;缺点是空间分辨率受限,上采样后边缘细节会比较模糊,近景物体的轮廓处容易出现过平滑。

很多复现版本在实现时会采用类似下面的结构,注意这只是一个工程参考,不完全等同于论文原版网络:

网络层输出尺寸说明
输入层H×W×3RGB图像,除以255归一化
卷积层1:3×3,32通道,ReLUH×W×32提取低级特征
池化层:2×2(H/2)×(W/2)×32扩大感受野
卷积层2:3×3,64通道,ReLU(H/2)×(W/2)×64提取中层特征
池化层:2×2(H/4)×(W/4)×64进一步压缩
卷积层3:3×3,128通道,ReLU(H/4)×(W/4)×128提取语义特征
全连接层低分辨率t向量映射为透射率图雏形
上采样:双线性插值H×W×1放大到输入尺寸

一个容易忽略的细节是损失函数的计算位置。如果网络先输出低分辨率t图再上采样,那逐像素损失是在上采样后的原图尺寸上计算,还是在低分辨率上计算,训练结果会有差别。按多数实现习惯,普遍做法是在上采样后对原图尺寸计算损失,梯度会穿过上采样层,让低分辨率特征也学会关注边缘区域的精度。不过这会增加训练开销,想要节省显存也可以先在低分辨率上算损失,再附加一个可选的边缘约束来补细节。

3.2 合成训练数据:用物理模型"伪造"退化水下图像

水下增强方向最大的痛点是缺少成对数据。真实水下拍摄几乎不可能在同一视角拿到"退化和清晰"两版照片,即便人为清理水体,光线、悬浮物、拍摄位置也不可能完全复现。论文采用的方法是用物理模型主动制造退化:取一张清晰的陆地图像作为J,随机生成透射率图t和背景光A,然后代入退化公式合成"水下图像"。

数据合成的伪代码大概是这样的:

import numpy as np def synthesize_underwater(J, A, t_mode="global"): H, W = J.shape[:2] if t_mode == "global": t = np.random.uniform(0.4, 1.0) t_map = np.full((H, W), t) else: # 平滑空间变化的透射率场,模拟不同场景深度 t_map = np.random.uniform(0.2, 1.0, size=(H//8, W//8)) t_map = np.kron(t_map, np.ones((8, 8))) t_map = np.clip(t_map, 0.1, 1.0) I = J * t_map[..., None] + A * (1 - t_map[..., None]) return I, t_map

这里的难点全在"随机生成"上。t如果是整图统一常数,模型学到的就是全局去雾;t如果做随空间平滑变化,模型还要理解场景深度差异。A的采样则模拟不同水体的背景光,常见的做法是让RGB三个通道在0.4到1之间随机采样,并让蓝绿色通道偏高,使合成图像更接近真实水下的偏色。合成数据的好处是能拿到逐像素精确的t真值,训练时直接监督;坏处是和真实水体的光学特性仍有差距,后面实验部分会看到这个差距带来的泛化问题。

3.3 损失函数与训练配置的细节

论文的损失函数极其简单,就是对估计透射率图和真实透射率图做逐像素MSE。这个选择看着朴素,其实很有针对性:透射率图取值范围固定,输出是单通道,任务本质是回归而不是图像生成,不需要感知损失、对抗损失那套复杂设计。MSE对小误差敏感,梯度传播稳定,配合简单的网络结构足够奏效。

训练时有几个配置需要留意。输入图像尺寸会影响全连接层之前的特征维度,训练和推理最好保持一致,中途改尺寸会出现维度不匹配。学习率方面,MSE返回的梯度本身不大,过大的学习率会导致loss曲线剧烈震荡,太小又会收敛极慢,建议从1e-4这个量级起步,配合学习率衰减策略。输入图像归一化到0~1区间是必要操作,不要带着0~255的原始像素值直接进网络,否则前几层卷积的输入范围过大,数值很容易失控。最后,透射率图的下限约束强烈建议做:恢复公式里有1/t项,t接近0时噪声会被极度放大,通常限制到0.1到0.2之间。

4. 实验设计中的亮点与局限:指标、对比与泛化问题

论文的实验分成两条线:合成测试集上算量化指标,真实水下图像上做主观视觉比较。这个设计当时很标准,因为真实水下图像没有参考真值,只能靠人眼判断色彩和细节是否自然。

合成测试集上的指标一般用PSNR和SSIM。PSNR衡量像素级重建误差,数值越高代表与原图越接近;SSIM衡量结构相似性,更贴近人的结构感知。这里有个容易被忽略的陷阱:合成测试集的参数分布如果和训练集完全一样,考的就是记忆力而不是泛化能力,模型可能只是记住了训练时的t和A模式。有参考价值的实验,应当让测试时的退化条件与训练分布错开。读论文时把不同退化强度、不同背景光颜色下的指标放在一起对比,会比只看一个平均分数更有信息量。

4.1 与其他经典方法的对比

这篇论文横向对比的方法大致分三类:第一类是直方图均衡类方法,速度快、不依赖模型,但容易过饱和、色彩失真;第二类是基于融合的方法,通过设计权重图把多张增强候选融合起来,效果好一些,但权重设计依赖场景;第三类是基于暗通道先验的系列方法,在大气去雾上表现好,放到水下因为暗通道假设失效,容易把大片蓝绿色背景误判成雾,透射率估计偏高,恢复结果偏暗。

CNN方法在这类对比中胜出的关键,不是网络多复杂,而是它通过大量合成数据学到了更贴近真实映射的t估计。手写先验总有特定适用范围,数据驱动方法在训练分布覆盖到位的情况下,统计上更接近真实函数。但要注意,这个优势不是绝对的。如果训练分布没有覆盖某些罕见退化,传统先验模型反而因为假设稳定而不会崩得太离谱。这也是为什么论文实验部分总会特意挑一些"非典型"水下图像来展示,目的就是看模型在分布外场景下的表现如何。

4.2 局限性与论文没有明说的部分

论文方法有一个重要的应用前提:整张图像共享同一个全局背景光A。合成数据里这个假设完全成立,但真实水下场景中可能出现太阳光斑、多光源、水面波浪折射聚焦等,背景光在空间上并不是常量。全局常数A的假设一旦偏离,恢复图的色温就会整体漂移。

另一个简化是单通道透射率。真实水下光的衰减是波长相关的,红光衰减快,蓝绿光衰减慢,严格来说每个颜色通道都应该有不同的透射率。论文用一个统一的t去反推三通道,只能部分拉伸色彩,无法彻底纠正由波长选择性衰减导致的偏色。这也是为什么模型在某些原图严重偏蓝的测试图上,恢复结果仍会残留一层青蓝色调。后来的很多水下增强工作正是沿着"分通道估计透射率""加入色彩补偿项""同时回归A和t"等方向做改进,如果你顺着引用顺着往后看,会明显感受到这条演进脉络。

5. 从论文阅读到复现实操:实现细节、踩坑与改动建议

读论文和复现论文是两码事。下面这部分是我自己动手实现这个方法时积累的经验,希望能帮你少走弯路。

5.1 复现时最容易踩的三个坑

第一个坑是背景光估计。合成训练时A是采样出来的,测试时得从输入图像里估计,最常见做法是算暗通道图,找最亮像素在原图的位置,把那里的RGB值当作A。但暗通道最亮处可能是白色目标物或者阳光直射区,并不代表背景光,直接取最亮值容易把A估高。稳妥一点的做法是先对暗通道做强高斯平滑,再取高百分位亮度对应的原图像素值作为A,或者对前0.1%最亮像素做平均。A一旦偏差明显,整张图的色温都会带偏,这个环节值得多花时间调试。

第二个坑是透射率下限。恢复公式里的1/t项在t趋近0时会把噪声放到无限大,黑暗区域会出现成片噪点和色块。解决办法是在得到网络输出后做一次clip:低于0.1的t强制置0.1,或者更高一点置0.2。论文正文对这个细节可能只是一句带过,但它确实是实现里绕不过去的必需操作。如果你复现后暗部出现明显噪点,先别急着怀疑网络结构,检查一下有没有做截断。

第三个坑是训练数据分布。A和t的采样范围如果太窄,模型在真实场景里会因为输入分布外而失效;太宽又会生成大量严重失真的合成图,让网络在相互矛盾的样本之间学不出稳定的映射。按我的经验,t在0.2到1之间平滑变化起步,A的RGB通道在0.4到1之间采样,同时让蓝绿色通道略高,这样生成的数据分布比较接近真实水下环境。当然这不是铁律,具体还是得根据测试集效果反推:如果真实图上蓝色残留过重,可以加重A的蓝绿偏移;如果整体欠曝,就调高A的下限。

5.2 损失函数验证链路和经验排查

复现时建议按以下顺序验证管线是否正确:第一步先固定A为合成时的真实值,喂给网络的输入图如果合成自干净图就能直接反推,这时网络输出t应该接近真实t,恢复图J也接近干净图。如果这一步就有问题,说明网络训练没有收敛或数据管线有bug。第二步改用暗通道法估计A,观察J是否仍然正常。第三步再换到真实水下图像,这时效果出现退化是正常的,重点看退化方式是否符合论文里描述的形态。

排查管线时有一个实用的检查点:打印中间产物I(合成退化图)、t预测图、A估计值、最终J。很多问题一眼就能看出是t预测糊了,还是A估计偏离了。比如J整体偏红,可能是A的红色通道估低了;J边缘出现白边,可能是t图过度平滑导致物体轮廓周围t过大。把中间结果可视化出来,比盯着loss曲线猜要高效得多。

5.3 对原方法可以做哪些实用改动

顺着论文思路,我后来做过几个简单但有效的改动。第一个是把上采样后的t图和原始输入图叠起来,送进一个小型精修网络细化边缘透射率,能明显改善前景物体边缘的伪影。第二个是把全局常数A改为空间渐变图,通过一个小网络同时回归A和t,训练难度确实变大,但对非均匀光照的真实水下图效果提升明显。还有一个零成本改动:训练时对输入图像做随机色彩抖动,相当于扩充背景光的分布范围,可以提升真实场景的泛化表现,且完全不改变网络结构。

5.4 这篇论文适合什么状态的人读

总结一下我对这篇论文适用人群的判断。如果你刚接触图像增强方向,想理解"成像物理模型+深度学习"这套经典组合的思考方式,这篇是很合适的入门深度解析对象,它不要求多前沿的网络结构基础,但对物理模型的理解有要求,建议先把Jaffe-McGlamery模型的推导在纸上过一遍。如果你已经用传统方法做过水下增强,想看数据驱动方法怎么融入传统管线,这篇也是一个很好的切入点。

最后说一句个人体会。读这篇论文最大的收获不是复现了一个水下增强算法,而是理解了一个方法论层面的选择:在数据和先验都不完美的时候,不要试图让模型一口吃掉整个问题,把问题拆成几个环节,把每个环节交给最适合它的工具,反而能获得更稳定、更可解释的结果。这个思路在我后来做其他图像复原任务时也一直受用。如果你正在做水下图像方向,建议看完这篇后,顺手把透射率可视化出来看看。t图会告诉你模型"眼里"哪些地方远、哪些地方近,也能直观暴露合成数据生成时没考虑到的真实场景结构。能把这个中间产品看明白,才算真正把这篇文章读透了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询