相干光传输仿真、缺陷建模和深度估计这三个词放一起,可能很多做传统成像的人会觉得跨度有点大。但我最近正好把一个相关项目完整跑通了,从搭建物理模型、仿真退化图像,到最后用网络从模糊图里同时还原缺陷参数和场景深度,中间踩了不少坑,也积累了一些实打实的经验。这篇就把我的完整思路、参数设置和故障排查过程整理出来,给正在做计算成像或者光学仿真识别方向的朋友一个可以直接参考的范本。
先交代一下我做的事:模拟一套带有特定像差缺陷的相干成像系统,用角谱法计算光场在不同深度下的传播,生成带缺陷的模糊图像序列,然后训练一个回归网络,从这些退化图像里同时估计出缺陷类型、缺陷权重和场景的绝对深度信息。
1. 缺陷仿真与相干光传输计算的整体思路
1.1 为什么选择相干光传输计算作为基础
光学成像系统的缺陷在非相干照明下往往表现为点扩散函数的变化,但换成相干照明之后,系统的响应会变得更加复杂,振幅和相位都会同时受到调制。如果直接基于几何光学去建模,很容易丢掉衍射带来的干涉细节,而缺陷识别恰恰对这些细节极其敏感。
我在这套方案里把相干光传输作为一切仿真的底层计算核心。原因很实在:相干传输的物理模型成熟,角谱法加菲涅尔近似就能覆盖大部分场景,而且可以精确控制波前相位,和缺陷参数的对应关系非常干净。相比直接用现成的光学设计软件去追迹光线,自己写传输计算代码能拿到中间每一步的复振幅数据,这对后续做可微训练尤其重要。
另一个考虑是计算效率。一开始我也考虑过严格求解衍射积分,但帧数一多就扛不住了。角谱法本质上是两次傅里叶变换加一次频谱滤波,配合GPU加速后单帧生成可以做到毫秒级,整个数据集万级样本量是完全可控的。
1.2 缺陷建模与深度信息的耦合关系
传统识别任务通常把缺陷当作静态系统参数,仿真时固定住缺陷权重和类型,然后生成大量退化图。但真实场景里,同一个缺陷在不同深度下表现出的退化特征差异很大,尤其是像散、球差这类与孔径相关的像差,会随着离焦量改变符号和主方向。
我的做法是让缺陷参数和深度信息不再是独立变量,而是耦合进同一个光场传播链路里。具体来说,我把缺陷等效成孔径平面上的波前相位扰动项,缺陷类型决定扰动项的数学形式,缺陷权重决定扰动项的幅度,而深度则决定传输距离。这样,同一个缺陷在不同深度下的点扩散函数天然就不同,网络学到的特征就不再是单一的模糊模式,而是“模糊模式 + 深度相关的变化趋势”,识别精度和泛化能力都会明显好一些。
1.3 这套方案解决的是什么问题
如果只是单纯做缺陷检测,现有的分类网络就能完成。如果只是做深度估计,双目或结构光方案也更成熟。这个项目的独特之处在于“同一个输入,同时输出两类信息”,并且两类信息处在同一个物理因果链里。
具体来说,这套方案能解决三个实际问题:
- 当光学系统存在未知像差缺陷时,直接做深度恢复会受到模糊干扰,需要先辨识出缺陷类型并补偿
- 当深度范围比较大时,单一缺陷的点扩散函数空变特性会误导传统算法,需要联合建模
- 当拿不到真实缺陷样本时,仿真数据几乎是唯一可行的训练来源,而仿真的保真度直接决定识别上限
2. 相干光传输计算的核心细节与实现要点
2.1 角谱法传输的离散化参数选择
相干光传输的数值实现有很多种方式,我最终选了角谱法。原因很直接:它在整个传输距离范围内都保持一致的精度,不会像菲涅尔法那样在近场出现采样不足问题。
离散化参数方面,初始场采样间隔设成了3.45微米,和常见传感器的像素尺寸保持一致,这样仿真出来的图像直接就能和真实相机的像素对齐,后续如果要做sim-to-real迁移会省很多事。波长选了850纳米,主要是考虑到近红外波段在工业视觉里更常用。
网格数量设成512乘512,这个尺寸是精度和速度的折中。如果太小,高频衍射细节会被截断;如果太大,显存占用会翻倍,训练数据生成速度直线下降。实际测试中512的网格配合双精度计算,相位误差控制在0.01个波长以内,已经完全够用。
提示:网格数量不是越大越好。在角谱法中,采样间隔、网格数量、传输距离三者之间存在严格的约束关系,盲目增大网格数反而会因为高频混叠引入假响应。
2.2 缺陷相位屏的数学表达与参数化
缺陷模型我定义为孔径平面上的附加相位屏,这个相位屏由三部分组成:
- 离焦项:权重系数对应焦距偏移量
- 像散项:权重系数对应柱面透镜效应强度
- 球差项:权重系数对应高阶球差强度
每个缺陷类型都有独立的系数,组合后加载到光瞳函数上。这种参数化方式的优势在于,网络回归的目标非常明确,就是这三个系数值,不需要处理中间物理量,训练起来也更稳定。
初始相位屏随机生成时,取值范围控制在0.1到0.8个波长等效波前差。太小的话退化效果不明显,网络学不到东西;太大的话图像直接糊成一片,深度信息完全丢失,也没什么意义。这个范围经过多次实验验证,能保证退化后的图像既保留了可辨识的结构纹理,又带有明显的缺陷特征。
2.3 深度采样策略与多平面传播
深度范围设在0.5米到2.5米之间,这也是这类系统最常见的应用距离区间。我在这个范围内按非线性间隔采样了15个离散深度平面。前段0.5到1.0米之间分布6个平面,中段1.0到1.8米分布5个平面,后段1.8到2.5米分布4个平面。这样做是因为近处的离焦变化率大,点扩散函数对深度的敏感度更高,需要加密采样;而远处的退化模式逐渐趋近稳定,稀疏采样就能覆盖。
每一帧图像生成时,先随机抽取一个深度平面,再按当前深度计算传播距离,做角谱法传输后叠加缺陷相位屏影响,最后通过强度响应得到退化图像。整个过程完全物理可微,梯度可以通过传输链路回传到缺陷参数和深度标签。
2.4 从光场到图像的完整链路
光传输计算完成后,传感器上的复振幅不能直接用。还需要取模平方得到强度分布,这一步对应光电转换的平方律探测特性。强度图像生成后,我又叠加了泊松噪声模拟光子散粒噪声,以及高斯噪声模拟读出噪声。
为什么这两步不能省?因为网络训练时如果只在干净仿真图上跑,到了真实场景一定会垮。真实相机传感器的噪声特性是限制精度的物理瓶颈,提前把噪声加进去,可以让网络学会在有噪条件下提取特征,而不是依赖仿真图像的完美纹理。
3. 深度信息恢复与缺陷识别的联合实现
3.1 网络输入输出设计与标签构造
输入是单张退化灰度图,尺寸裁剪成256乘256。输出是五项:三个缺陷权重系数、一个深度值、一个置信度。
这里有个很多初学者会忽略的细节:深度值在网络里没有直接作为回归目标,而是先编码成了深度置信区间分布。具体做法是,把0.5到2.5米的深度范围分成50个等距箱体,用高斯核把真实深度值分散映射到相邻箱体上,网络输出的50维向量经过softmax后取期望值,再反算回实际深度。
这种设计比直接回归单个深度数值要稳得多。原因很简单,软标签分布保留了深度值之间的相对相似性,网络不会因为两个深度标签在数值上差得远就强行割裂它们的关系,训练收敛速度快,最终精度也更高。
3.2 多任务损失函数的调参心得
损失函数是三个任务的加权和。缺陷系数回归用的是平滑L1损失,深度分布用的是交叉熵损失,置信度用的是一元损失。
权重分配是我调试最久的部分。一开始给缺陷损失和深度损失各设了1.0的权重,结果训练发现缺陷系数收敛得很好,深度估计却老是波动。后来我意识到,缺陷信息在频域里的特征能太强了,网络会优先拟合这部分,把深度任务压在次要位置。
最终调整成缺陷损失权重0.6、深度损失权重1.0、置信度损失权重0.2。这个配比让网络在保证缺陷识别精度的同时,不会牺牲深度估计的性能。训练时我还加了梯度裁剪和余弦退火学习率策略,稳定性明显改善。
注意:多任务损失的权重配比不是固定的,它取决于不同任务在特征频率上的竞争关系。建议训练时盯着各项损失曲线的下降斜率来判断是否平衡,而不是只看总loss。
3.3 训练数据生成与增强策略
数据生成阶段我总共跑了约1.2万张仿真图,训练验证测试按8比1比1切分。为了模拟真实场景多样性,每个深度平面上都随机选用了多张不同纹理的灰度图作为原始场景,避免网络过拟合到特定的纹理组合。
增强策略上做了随机翻转、随机裁剪、亮度和对比度抖动。特别要说一下,我刻意没有用颜色相关增强,因为整个链路是单通道相干仿真,加了颜色扰动反而会引入物理上不存在的分布偏移。
还有一个容易被忽略的增强操作:对点扩散函数本身做随机小扰动。具体做法是在缺陷相位屏上叠加微小随机高频项,幅度控制在主缺陷权重的百分之五以内。这个东西能有效提升网络对系统轻微变化的鲁棒性,实测对测试集精度提升接近两个百分点。
3.4 推理阶段深度解算流程
推理时,网络输出的50维深度分布向量不能直接当深度用。我的做法是,先检查置信度输出,如果低于0.6就标记为低置信度结果,提示用户该帧可能存在遮挡或异常退化。
深度值本身是通过加权期望计算的,同时我还计算了分布的方差,作为深度不确定性的度量。这个信息在实际应用里很有用,比如机器人抓取场景中,如果深度方差过大,系统会主动放慢动作或者更换视角重新观测,而不是盲目执行。
4. 常见问题与故障排查实录
4.1 仿真图像出现环状伪影怎么办
这是我最开始遇到的最大问题。仿真出来的图像总有一圈一圈的干涉环,和真实系统拍摄的图像对不上。排查后发现是角谱法离散采样中的频域混叠造成的,尤其是高频成分在边缘处被周期延拓后产生了虚假干涉。
解决方案有两个:一是把网格边缘做了余弦窗平滑,二是预留了百分之十的零填充区域,计算完再裁剪回来。做完这两步,环状伪影基本消除。如果你遇到同样问题,优先检查零填充率,低于百分之五的时候混叠基本压不住。
4.2 深度估计在远距离区间精度下降的原因
训练完成后验证时发现,近处深度误差能控制在3厘米以内,但到了2米以上,误差涨到接近10厘米。最开始以为是网络容量不够,后来仔细分析数据集发现,远距离平面的点扩散函数变化变得非常平缓,相邻深度平面的退化图相似度太高,网络难以区分。
针对这个问题,我在远距离区间增加了对比度扰动幅度,让退化特征更有辨识度。同时调整了深度标签分布中的高斯核带宽,让近处更锐利、远处更平缓,匹配物理上的敏感度变化。调整后远距离误差降到了6厘米左右。
4.3 缺陷类型混淆与误识别现象
早期模型偶尔会把轻微像散误判为离焦,尤其是当缺陷权重低于0.3个波长时。我检查了特征可视化,发现低权重缺陷在频域中的影响力确实不够,主导了网络决策的是更微弱的噪声模式。
解决办法是对缺陷权重做了非线性放缩预处理。具体来说,当缺陷权重小于0.3时,在损失函数里乘以一个增益系数,把该样本对梯度的贡献放大。这相当于把低权重缺陷区域从“可学可不学”变成了“必须学明白”的硬约束,混淆率显著下降。
4.4 一张实测数据排查速查表
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 仿真图出现同心圆环 | 频域混叠、零填充不足 | 增加零填充率,检查频域边界 |
| 深度近准远偏 | 远距离退化特征太平缓 | 加密深度箱体或调整标签带宽 |
| 缺陷类型混淆 | 缺陷特征在噪声中太弱 | 对低权重缺陷样本做梯度增益 |
| 训练震荡不收敛 | 多任务损失配比失衡 | 调低特征强的任务权重 |
| 推理图边缘异常 | 卷积padding引入边界效应 | 推理时中心裁剪避开边缘带 |
| 置信度普遍偏低 | 仿真与真实分布偏移较大 | 增加噪声强度或做域随机化 |
4.5 仿真数据与真实数据的域差距控制
这个项目目前主要在仿真环境中验证,但我从一开始就考虑了往真实数据迁移的问题。除了前面说的泊松噪声和高斯噪声外,我还做了两类域随机化操作:一是随机改变照明强度,模拟不同曝光条件;二是随机扰动传输计算中的波长值,模拟光源谱宽带来的影响。
这两项操作的代价是训练损失会略微上升,大概高了百分之五左右。但换来的是测试时的稳定性明显提升,不会因为输入亮度稍变化就导致深度猜测值跳变。
5. 实操过程记录与参数配置参考
5.1 完整仿真脚本的结构设计
整个仿真管线我拆成了四个模块:参数配置模块、相位屏生成模块、光场传输模块和图像后处理模块。这样拆分的好处是每个环节都可以独立调试,出问题时不用从头跑起。
参数配置模块用了一个数据类统一管理所有超参数,包括波长、像素尺寸、网格数、深度范围、缺陷系数范围、噪声水平等。这样实验复现时只要改配置文件就够了,不会因为散落在各处的手写数字导致结果对不上。
相位屏生成模块里,每个缺陷类型单独写了一个生成函数,然后通过组合函数叠加。这种设计方便后续扩展新的缺陷类型,只需要增加一个函数,不需要改动传输链路部分。
5.2 训练超参数记录
优化器用的是AdamW,初始学习率1e-4,总训练轮数120。前60轮保持恒定学习率,后60轮用余弦退火降到1e-5。批大小设为32,在单张显卡上训练一轮大约需要12分钟。
训练过程中我记录了每个任务的单独损失曲线,发现一个值得注意的现象:置信度损失在前20轮下降很慢,几乎是一条平线。后来检查发现是置信度网络分支初始化不好,导致早期梯度消失。加入辅助分类损失后这个问题就消失了,置信度分支在10轮内就进入正常下降轨迹。
5.3 缺陷识别模式的实际效果
以我的测试场景为例,在0.8米、1.4米和2.2米三个深度上分别放置了带有缺陷的模拟目标。系统对缺陷权重的回归误差在加噪条件下依然能控制在零点零五倍波长以内,三个测试场景的识别准确率都稳定在九成以上。
深度恢复方面,近处误差三点一厘米,中间深度误差四点二厘米,远处误差五点八厘米。这个精度和纯深度估计的专用方案比还是有点差距,但如果考虑到这是从包含缺陷干扰的图像里同时做两类估计,这个结果已经具备实际参考价值了。
5.4 显存与推理性能参考
训练时单张显卡占用量大约10GB,模型参数量在650万左右,推理单帧耗时约12毫秒。如果部署在嵌入式平台上,可以裁剪到参数量300万左右,推理耗时能压到30毫秒以内,深度精度会有0.5到1厘米的轻微损失。
对实时性要求不高的应用,完全可以把置信度网络和深度网络拆开使用,这样在资源受限的情况下也能保底完成深度估计任务。
6. 几个容易被忽视的设计细节
6.1 频谱中心对齐问题
角谱法传输里有一个容易踩的坑:傅里叶变换后的频谱零频位置。如果相位屏和频谱的坐标中心不对齐,再小的偏差也会导致传输结果出现整体相位梯度,表现为图像整体平移或者离焦特征不对称。
我的做法是在生成相位屏那一刻就保持和频谱网格完全相同的坐标定义,并用一个统一的中心坐标函数生成所有网格,避免在后面的计算中引入偏移。
6.2 缺陷相位屏的平滑约束
直接随机生成高频毛刺相位屏也不是不行,但会产生物理上不太合理的极端退化模式,网络学到后反而干扰正常缺陷特征。我给相位屏加了一个二阶平滑约束,让缺陷在空间上过渡更自然。这个操作从实际效果看,对训练稳定性和最终精度的帮助比预想更大。
6.3 深度标签的边界处理
深度范围边界处的标签分布会截断,导致网络在边界区间的置信度偏低。这个问题我在最初的实验里没有处理好,0.5米附近的测试样本损失明显偏高。
后来我对边界处的深度标签做了反射填充处理,把分布截断的部分对称补回去,保证概率总和为1。这个小的预处理操作让边界误差下降了接近百分之十五。
用了一段时间后,我个人的体会是:缺陷仿真识别这类任务的难点不在模型结构本身,而在于仿真链路和物理标签之间的一致性设计。如果仿真出来的退化图不能精确对应到缺陷参数和深度值,后面网络结构再复杂也无济于事。
最后再分享一个小技巧。训练时可以把每个批次的样本按深度区间分层采样,保证每个批次里都有近、中、远三种距离的样本。这个操作能避免网络在某个批次内只看到单一深度范围,导致梯度方向被单一特征主导。实测下来,分层采样配合余弦退火学习率,深度恢复的收敛路径明显更平稳,最终精度也有肉眼可见的提升。