
简介面向光学成像与信号处理方向学习者这份资源以 MATLAB 脚本形式呈现重建算法示例包解决从测量数据中恢复原始波面的核心问题。内容围绕波面重建主题提供菲涅尔算法、卷积方法、傅里叶变换三条实现路径菲涅尔算法适用于近场传播模拟卷积方法通过点扩散函数建模成像退化傅里叶变换则用于频域滤波与逆变换恢复帮助理解各类方法的数学原理与编程实现。资源共3个文件全部为.m脚本压缩包仅7KB体积精简、便于直接查看源码适合动手调试。文件涵盖菲涅尔重建、空间载波傅里叶变换、卷积重建等典型场景分别演示对应算法在波面恢复中的具体步骤。目前已有240人学习下载通过这套脚本可快速复现硬币波面重建实验对比不同算法效果差异为课程设计、毕业设计或相关科研提供可直接修改的基础代码。1. 重建算法与重建波面先搞清你拿到的是什么再谈重建探到强度图的第一反应往往是挑重建算法但真正决定重建波面质量的是你对数据类型的理解。重建算法的任务是强度记录中恢复复振幅这里面既有衍射模型的近似误差也有离散采样的系统约束不是简单的图像锐化或滤波。同一个全息图用菲涅尔重建和角谱重建得到的结果在尺度、曲率、细节上都不相同差异背后的原因是数学模型而非代码实现。接下来的内容把波前重建涉及的算法边界、最小可复现Python实现、参数排错和验证手段串成一条可落地的路径先看算法和选型再看代码和参数最后聊没有标准样品时的验证方式。这块内容适合计算成像、全息显微和自适应光学方向的新手也照顾到需要定量比较不同重建算法结果的经验工程师。2. 重建波面的三种主流算法菲涅尔、角谱与卷积法的选型依据2.1 菲涅尔重建算法一次FFT但有近似边界菲涅尔重建算法基于标量衍射理论中最常用的近似做法把球面波因子做二项式展开保留到二阶使得衍射积分退化为一个单次傅里叶变换。数字实现上它只需一次FFT因此在长距离传播、远场发散的激光光斑和平坦波前测量场景里效率优势明显。很多商业软件与开源库的默认重建入口都是它因为速度最快。但是用之前一定要检查是否满足近轴近似。常见判据是最大孔径差带来的四次相位项远小于一个弧度即 z³ 的数量级要明显大于 π/(4λ) 乘以最大孔径坐标差的四次方。实际工程里我一般看传感器半宽 a设 a2mm、波长532nmz 至少要到达厘米量级才基本成立如果记录距离只有几百微米近轴近似误差过大重建波面上会出现明显的高频波纹状伪影。菲涅尔重建在离散域还有一个固有尺度问题输出平面像素尺寸会随 z 线性放大公式为 Δout λ·z/(N·Δin)。搜索聚焦位置时如果用多个 z 值重建每一轮波面的横向标尺都在变。对比不同 z 下的曲率或残差必须先重采样到公共网格否则弧度读数的差异里有相当一部分来自像素尺寸缩放而不是真实波前起伏。2.2 角谱重建算法瑞利-索末菲框架下近场远场都能重建角谱法不做近轴近似把光场展开成平面波角谱传播过程只对每个平面波分量施加一个相位延迟。离散域计算是两次FFT先对输入复振幅做二维FFT得到角谱乘上传递函数 H(fx,fy) exp(i·k·z·sqrt(1-(λfx)²-(λfy)²))再做一次逆FFT回到空域。计算开销大约是菲涅尔法的两倍但换来的好处是没有距离限制。近场、远场、甚至零距离都能保持同一套公式输出像元大小保持不变这对全息显微这种高频信息占比高的场景非常关键。实践里角谱法还适合做批量扫描。虽然多一次FFT但代码没有分支NumPy批量实现时内存访问模式非常规整配合多组 z 并行计算反而比循环调菲涅尔法更快。我通常先用角谱法做一轮粗扫确认焦面位置再决定是否需要更细的步进。角谱法真正的细节在传递函数的截止频率处。当 (λfx)²(λfy)² 超过 1对应的是倏逝波区域理论上这部分能量指数衰减对远场重建没有贡献。数值计算时必须把根号内负值截断为 0不能保留负值让它流入复指数否则传递函数会变成指数放大项让重建波面边沿出现一排排等间距的环形伪影。这个截断操作要写在算法内部不要依赖外部掩膜因为掩膜和频率网格错位时反而会引入新的边界衍射。2.3 重建算法选型对照表与边界条件算法FFT次数距离适用范围输出像素尺寸主要使用误区菲涅尔法1满足近轴近似的中远距离随z放大近距离数据直接套用波面高频崩坏角谱法2任意距离近场更稳不变遗漏倏逝波截断边界出现环状伪影卷积法3系统不变的中等距离基本不变频率原点未对齐出现整面偏斜选型时把权重放在距离限制和像素尺寸稳定性上。扫描聚焦范围时优先菲涅尔一次FFT能快速试探几十个 z定量测量和近场重建用角谱法。卷积法除非要模拟成像系统传递函数或处理非平面参考波否则不是我的首选多一次FFT的代价换来的增益不明显。这三种算法的边界条件最后都落在采样端。所有重建算法的分辨率上限都受传感器奈奎斯特频率限制算法能做的是保持频带内信息不畸变超出传感器分辨率的波前细节三种算法都无能为力差别只是各自用不同方式把混叠失真呈现出来。3. 实现重建波面的最小闭环从全息图到相位的Python骨架3.1 角谱法实现重建波面的核心函数直接用角谱法写一个最小可复现核心输入二维复数场输出传播 z 距离后的重建波面。只有强度数据时先用强度开方作为幅度、相位初始化为 0再进入迭代细化流程。import numpy as np from numpy.fft import fft2, ifft2, fftfreq def asm_propagate(u_in, wavelength, pixel_size, z): 角谱法重建波面。 u_in: 输入复振幅只有强度时取 sqrt(I) 作为幅度相位先填 0 wavelength: 波长和 pixel_size 使用同一长度单位 pixel_size: 传感器实际采样间隔 z: 传播距离正值代表沿光轴正向 rows, cols u_in.shape # 空间频率坐标与 fft2 输出的频谱排布一致 fx fftfreq(cols, dpixel_size) fy fftfreq(rows, dpixel_size) FX, FY np.meshgrid(fx, fy) k 2 * np.pi / wavelength radicand 1.0 - (wavelength * FX) ** 2 - (wavelength * FY) ** 2 # 截止频率之外的区域按倏逝波处理直接置零 radicand[radicand 0] 0.0 H np.exp(1j * k * z * np.sqrt(radicand)) U_out fft2(u_in) * H u_out ifft2(U_out) return u_out代码里fftfreq是关键细节它按 FFT 输出顺序返回频率点与fft2得到的频谱位置严格对齐。如果习惯用fftshift把频谱挪到中心就必须对频率网格也做同样的fftshift这两条语句漏掉任何一条重建波面会变成满屏高频乱纹而不是能解释的相位图。radicand[radicand 0] 0这行是角谱法的安全阀。如果不截断根号内为负的区域会让sqrt返回 na nna n 在np.exp里会扩散成整个复数场的污染即便避开 na n负值区域的复指数也可能变成指数放大项产生大幅边界振铃。3.2 重建算法的三个核心参数波长、像素尺寸、距离波长、像素尺寸、记录距离这三项参数共同决定重建波面的相位尺度。波长直接影响相位到物理高度的换算干涉测量里一个弧度对应的光程差是 λ/(2π) 的整数倍关系如果重建后要把相位换算成纳米级高度波长单位记错一个数量级高度读数就会错得离谱。像素尺寸是很多人忽略的隐藏变量。实验系统里如果有 4f 放大或显微物镜传感器实际像素需要除以放大倍率才是重建算法里要填的等效采样间隔。常见做法是先用分辨率板标定放大倍率再把相机标称像素尺寸换算完填入。不做这一步重建波面的斜率会成比例错误填大了波面显得平坦填小了波面剧烈起伏。记录距离在角谱法中只是一个正负号和标量倍数但方向约定容易出错。我习惯把“光从物面传播到记录面”定义成正逆向重建用负的 z。如果正反弄反重建波面的相位曲率会反向整体看起来像一张凹透镜相位图这种错误和真实像差很难区分需要借助已知平面参考光做对照。参数推荐做法参数出错时的表现wavelength用激光器中心波长如 532e-9相位值整体缩放斜率变化不随样品移动pixel_size相机像素÷系统放大倍率重建波面呈对称离焦状高频边缘失真z按光路物理距离先估再微调正负反时曲率反转偏大出现额外二次相位3.3 相位提取、背景去除和解包裹的顺序拿到复振幅后相位提取本身是一行代码np.angle(u_out)但你把什么数据送进这一行直接决定结果是否可信。直接对原始复振幅做相位提取、再走解包裹会把直流分量和低频照明不匀全部混进来最终相位图里多出一个类似下坡的整体倾斜背景。正确的顺序是先对复振幅做频域带通滤波滤掉直流峰和超出传感器截止区域的高频能量再提取相位。滤波在复振幅域进行有一个好处复振幅本身在信号区域连续频域窗口不跨越任何相位跳变不会像处理包裹相位那样在 ±π 边缘引入假条纹。解包裹放到滤波之后跳变区域仍然存在但背景噪声被压下去成功率会显著提高。之后再做 Zernike 拟合或斜率统计时先扣除整体倾斜项再分析残差相位。4. 重建波面的参数边界与排错伪影来自哪里4.1 采样带宽积与重建算法分辨率的边界重建波面的可分辨细节上限由系统的空间带宽积决定而不是由算法决定。换成实操说法就是传感器像素尺寸和像素数共同限定频域截止频率当波前斜率过大、条纹密度超过传感器奈奎斯特极限时重建算法无法分辨方向。这时强行提高重建分辨率得到的只会是混叠伪影。一个对相位梯度很有用的经验式可重建的横向梯度极限大约是 λ/(2Δx·z)。它解释了一个常见现象同一样品放远记录时重建波面细节变少原因不只在衍射低通还在于同一波前梯度对应的条纹密度随 z 变小了重建算法在频域上的支持范围相对变窄。因此调整重建距离时要意识到你改的不只是离焦量同时也在改系统的横向分辨率边界。4.2 重建波面伪影的排查顺序排错按确定性顺序进行不要上来就调平滑系数。第一步先数单位波长、像素、距离是不是同一米制体系。第二步看方向把 z 取反做一次重建观察相位曲率是否反转若反转则是符号问题而非算法错误。第三步看光强背景原始光强不均匀会在重建波面里引入球面背景分量把空场区域的复振幅均值减掉后再提相位能去除大部分这类伪差。第四步看边界振铃采样窗口边缘出现等间距环状条纹常见原因是没有对输入场做切边处理或者倏逝波区域未截断。这四步做完仍不干净的才需要考虑更换更强约束的迭代算法。很多“波面不平整”的问题根子在单位或方向一行代码都不用改就消除了多跑几轮迭代只会让错误的相位分布收敛到更精致的错误上。提示按步骤排查要比反复揉参数高效得多先把量纲和符号确认好再进入算法层面的优化。4.3 迭代重建算法GS循环的收敛边界与振铃抑制对于强度记录不含相位、需要反演未知波面的问题单次传播往往不够。常见做法是把前向传播当作已知算子用 Gerchberg-Saxton 迭代交替施加物面约束和记录面约束。核心循环如下直接使用前面定义的asm_propagatedef gerchberg_saxton(u_init, measured_amp, mask, wavelength, pixel_size, z, n_iters50): GS迭代重建波面。 u_init: 物面初值复振幅 measured_amp: 记录面实测幅度强度开方 mask: 物面支持域掩膜非零区域代表目标可能存在的范围 u u_init.copy() for i in range(n_iters): # 正传到记录面用实测强度约束替换幅度 u_rec asm_propagate(u, wavelength, pixel_size, z) u_rec measured_amp * np.exp(1j * np.angle(u_rec)) # 反传回物面用支持域约束限制能量位置 u_back asm_propagate(u_rec, wavelength, pixel_size, -z) u u_back * mask # 每十步输出一次残差便于观察收敛 if i % 10 0: res np.linalg.norm(np.abs(u_rec) - measured_amp) res / np.linalg.norm(measured_amp) print(fiter {i:3d}, residual {res:.4e}) return uGS 循环对 mask 的尺度和形态非常敏感。支持域设小了解被限制在局部极小附近收敛曲线会很快平掉支持域设大了约束力不足残差缓慢下降并伴随抖动。我的默认做法是先用 Otsu 阈值从反传振幅里提取大致目标区域再放大 10% 作为 mask跑 50 轮看残差曲线形态如果残差单调下降但尾部抖动明显说明 mask 边缘混入了孤立噪声点做一次形态学开运算再重新迭代。振铃是迭代重建里最常见的高频伪影。如果重建波面边缘出现等宽度明暗条纹而中心区域平滑大概率是 mask 边界太硬。硬边界在频域引入 sinc 状旁瓣迭代过程会把旁瓣进一步放大。缓解手段是对 mask 应用 3 到 5 像素标准差的高斯边缘软化或在每轮物面约束后乘一次切比雪夫窗做衰减。两者都不会明显增加计算量却能显著压低边沿振铃。5. 数值验证技巧没有标准波面时怎么确认重建算法是可靠的5.1 用数字体模生成已知波面标定重建算法最可靠的手段是构造一份数字样品生成已知的相位分布正向传播得到数字全息图再把全息图当作待重建数据跑完整流程最后与真值逐像素对比。yy, xx np.mgrid[-256:255, -256:256] / 256 phase_truth 1.2 * np.exp(-(xx**2 yy**2) / 0.3) u0 np.exp(1j * phase_truth) # 正传得到数字强度图再叠加泊松噪声模拟相机响应 intensity np.abs(asm_propagate(u0, 532e-9, 3.45e-6, 0.05))**2 measured np.random.poisson(intensity / intensity.max() * 5000)这一小段模拟覆盖了输入、传播和噪声三个环节。需要把measured转成幅度跑完整重建流程再提取相位做质量评估。5.2 三个重建波面快速评价指标第一个指标是相位残差标准差。取重建相位与phase_truth的差值去掉整体倾斜和常数偏移后统计残余标准差。0.1 rad 以内可以作为常规可用基准如果残差边缘大、中心小通常是边界振铃导致的带宽问题。第二个指标是结构相似度 SSIM它对局部相位梯度的保持更敏感可以防止一两个大误差点主导判断。第三个指标是边缘振铃比重建波面外圈 10% 像素的梯度幅值均值除以整体梯度幅值均值比值大于 1.2 说明存在边界振铃或窗口截断失配。5.3 验证流程的两轮设置第一轮使用无噪声数据验证算法逻辑和数值自洽度。目标是把残差压到 1e-8 弧度以下达不到就要检查频率轴与 FFT 对齐、波长单位、倏逝波处理。第二轮加入泊松噪声残差应随噪声水平近似线性上升。如果残差基本不动说明重建过程存在过强的平滑或正则化对真实的弱信号数据会造成过度平滑。验证时有一个容易忽略的细节模拟生成和重建算法必须共用同一份参数配置文件。模拟用 532nm、重建却填 633nm测出来的不是算法可靠性而是参数敏感性这种误标定会直接误导下一步实验设计。正确做法是在同一配置文件里读出两组参数分别供给生成器与重建函数确保验证的就是生产环境里的同一套数值管道。本文还有配套的精品资源点击获取