ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

数字全息实验全流程:干涉记录、数值重建与相位解包裹实战指南

数字全息实验全流程:干涉记录、数值重建与相位解包裹实战指南 简介数字全息实验涉及干涉记录与数值重建本资源面向光学工程、信息光学方向的学生和科研人员按照真实实验流程整理了一套FFT重建实例。压缩包内共3个文件1幅.tif实验全息图来源于实际采集可当作真实对象测试重建算法1张.png光路示意图完整展示干涉装置便于使用者理解物光与参考光的夹角、距离等关键构型1个.m程序以MATLAB脚本实现快速傅里叶变换重建能够从全息图直接恢复物光场的幅相分布。资源包整体仅1.79MB轻量且聚焦适合快速下载后结合教材开展验证实验。目前已有1104人学习/下载内容具备一定的通用性和参考意义。借助这套资料读者既能直接运行程序获得重建结果又能通过修改滤波窗口观察零级像与孪生像的消除效果从而深入理解频谱滤波、相位解包裹等核心步骤为后续从事数字全息显微或定量相位测量等实际应用提供技术参考。1. 数字全息实验到底在看什么第一次做数字全息实验的人通常会被两件事震住一是记录面上那张全息图看起来完全是随机噪声没有任何物体的样子二是在电脑里跑完一段重建代码后原本看不见的相位分布像变魔术一样浮现出来。这个过程的本质其实不神秘——全息记录把物光的振幅和相位一起编码进干涉条纹数值重建再把相位从条纹里解出来。和普通成像只能记录光强不同数字全息实验拿到的是复振幅相位信息可以直接换算成光学厚度、形貌高度或折射率变化这是它区别于普通显微成像的核心价值。这篇文章按一条完整的实验链路来讲先把记录和重建的物理模型理清楚再用 Python 把模拟全息图跑通接着落到实验台上的光路搭建与采集参数最后处理真实数据里最常翻车的相位解包裹问题。读完以后你可以直接拿这套流程处理自己采集的全息图。2. 从干涉记录到数值重建的完整链路2.1 记录面上的干涉物光、参考光与四项频谱数字全息实验的第一步是让一束物光和一束参考光在相机靶面上干涉。设物光复振幅为 O(x,y)参考光为 R(x,y)相机记录到的光强分布为I(x,y) |O R|² |O|² |R|² O·R* O*·R式子右边四项各有来头|O|² 是物光自相关项|R|² 是参考光强度这两项构成零级项直流项O·R* 和 O*·R 分别是原始像项和共轭像项。如果参考光严格沿光轴传播同轴全息四项在频域重叠在一起重建时原始像和共轭像会互相污染参考光与物光之间保持一个夹角 θ让干涉条纹带上一组空间载频四项频谱就会在频域分开这就是离轴数字全息实验避开孪生像的基本思路。离轴角度的选择不是越大越好。干涉条纹的周期 d 与夹角满足 d λ / sinθ而相机像素尺寸 Δx 必须小于条纹周期的一半才能满足采样定理否则条纹混叠。由此得到参考光夹角的上限sinθ ≤ λ / (2Δx)以常见的 532 nm 激光、3.45 μm 像素尺寸为例θ 最大约 4.4°。超过这个角度高频条纹直接混叠重建质量断崖式下降角度太小频谱分离不干净零级项会串扰到重建像。我一般会把夹角取在上限的 60% 到 80% 之间留出频谱滤波的过渡带宽。2.2 重建的数学操作菲涅尔衍射积分记录面拿到全息图以后重建在数学上等价于让透过全息图的光场继续传播一段距离 z。这个传播过程满足菲涅尔衍射积分。数字实现最常用的是卷积形式也叫角谱法U(x′, y′) F⁻¹ { F{ I(x, y) } · H(fx, fy) }其中传递函数 H(fx, fy) exp[ i·k·z·√(1 − λ²fx² − λ²fy²) ]fx、fy 是空间频率。角谱法的最大优势是输出像素尺寸与输入一致不会像单次傅里叶变换法那样因为传播距离不同导致像素尺寸漂移。在做实验数据时这省掉了一大堆换算。用角谱法重建时衍射场的采样间隔始终等于相机像素尺寸。重建距离 z 在实验里是一个需要标定的量如果用的是平行光参考光z 就是物体到相机的物理距离如果光路里加了透镜则需要通过自动对焦来估计等效距离。这个点后面专门展开。2.3 离轴数字全息实验的频率分离条件在频域里看|O|² 和 |R|² 的频谱集中在零频附近带宽由物体自身最高空间频率决定O·R* 项的中心位置由参考光载频决定偏移量为 (sinθ/λ, 0)。要完整分离三个级次参考光夹角对应的载频必须大于物体频谱带宽的 1.5 倍左右。这是一个工程经验值小于 1.5 倍时用窗函数硬切会把物体高频信息削掉重建像边缘发糊大于 3 倍则可能超出相机奈奎斯特频率得不偿失。主体思路清楚了接下来先在 Python 里把这一套流程验证一遍。用代码生成模拟全息图不仅能在没有光学平台的情况下理解每个参数的影响更重要的是能用来验证重建算法本身的正确性——如果模拟数据都重建不对就不要急着上实验台。3. 用 Python 生成并重建一张模拟全息图3.1 生成物光场与参考光模拟数字全息实验的第一步是构造一个已知的物光场。这里用一个相位型物体作为样例比如一个高斯型的相位凸起它模拟的是透明样品带来的光程差。然后构造一束与光轴成 θ 夹角的平面波作为参考光。完整代码如下import numpy as np # 实验参数 wavelength 532e-9 # 波长 532nm pixel_size 3.45e-6 # 相机像素尺寸 3.45um N 1024 # 采样点数 z 0.12 # 传播距离 12cm theta_deg 2.0 # 参考光与物光的夹角 2度 # 构建坐标网格 x (np.arange(N) - N / 2) * pixel_size X, Y np.meshgrid(x, x) # 构造物光场高斯相位凸起模拟透明样品 phase_obj 2.0 * np.exp(-(X**2 Y**2) / (2 * (200e-6)**2)) O np.exp(1j * phase_obj) # 透过样品的物光 A_obj np.ones_like(O) # 振幅取1纯相位物体 # 参考光与物光轴夹角 2 度沿 x 方向倾斜 fx0 np.sin(np.deg2rad(theta_deg)) / wavelength # 参考光空间频率 R np.exp(1j * 2 * np.pi * fx0 * X) # 生成干涉强度图数字全息实验的记录结果 I np.abs(A_obj * O R)**2这段代码里有几个参数直接对应实验台上的真实物理量theta_deg 是参考光夹角决定频谱分离程度z 是后续重建用的传播距离相位凸起的 200e-6 表示样品特征尺度是 200 微米。如果你的光路波长或像素尺寸不同改这三个量即可。需要注意的是 fx0 的计算空间频率等于 sinθ / λ单位是线对每米乘以 X 得到相位项。3.2 角谱法重建的完整函数生成全息图之后重建代码要完成四件事对全息图做傅里叶变换、频域滤波取出一个边带通常是 O·R* 项、逆傅里叶变换回空间域、再乘以角谱传递函数实现衍射传播。这里先不做滤波只演示完整传播。def angular_spectrum_propagation(U_in, wavelength, pixel_size, z): 角谱法衍射传播 U_in: 输入复振幅 wavelength: 波长(m) pixel_size: 采样间隔(m) z: 传播距离(m) N U_in.shape[0] fx np.fft.fftfreq(N, dpixel_size) FX, FY np.meshgrid(fx, fx) # 角谱传递函数忽略倏逝波分量 k 2 * np.pi / wavelength temp 1 - (wavelength * FX)**2 - (wavelength * FY)**2 H np.exp(1j * k * z * np.sqrt(np.maximum(temp, 0))) # 频域相乘再逆变换 U_out np.fft.ifft2(np.fft.fft2(U_in) * H) return U_out # 用全息图本身作为输入零级近似后续会改进 reconstructed angular_spectrum_propagation( I.astype(complex), wavelength, pixel_size, z ) # 提取重建相位 recon_phase np.angle(reconstructed)这段代码的核心是传递函数 H 的构造。temp 小于 0 的部分对应倏逝波在离物体几个波长的距离上就已经衰减到可以忽略取最大值截断是标准做法。z 的单位是米要和波长、像素尺寸统一。运行这段代码后recon_phase 应该能大致看到一个高斯形状的相位分布但会叠加很强的背景条纹——这是因为还没有做频域滤波零级像和共轭像的频谱混在一起。3.3 在频谱里做滤波分离原始像为了还原干净的物光场需要在频域把 O·R* 项单独切出来。操作步骤是先对全息图做傅里叶变换找到边带中心的坐标然后用一个圆形掩膜把它周围的频率分量选中再平移到原点。这相当于把离轴载频去掉让物光回到零频。from scipy import ndimage F np.fft.fftshift(np.fft.fft2(I)) fx_axis np.fft.fftshift(np.fft.fftfreq(N, dpixel_size)) FX, FY np.meshgrid(fx_axis, fx_axis) # 边带中心约在 (fx0, 0) 处转换成像素索引 center_pix_x int(round(fx0 / (fx_axis[1] - fx_axis[0]))) center_pix_x N // 2 # 圆形掩膜半径约为物体频谱带宽的1.5倍 bandwidth 1 / (200e-6) * 1.5 # 物体最大空间频率的1.5倍 radius_pix bandwidth / (fx_axis[1] - fx_axis[0]) Y_mask, X_mask np.meshgrid(np.arange(N), np.arange(N)) dist_from_center np.sqrt( (X_mask - center_pix_x)**2 (Y_mask - N//2)**2 ) mask dist_from_center radius_pix # 滤波取出边带并平移到原点 filtered F * mask filtered_shifted np.fft.ifftshift(filtered) object_wave np.fft.ifft2(filtered_shifted) # 数值传播到物平面 reconstructed angular_spectrum_propagation( object_wave, wavelength, pixel_size, z ) # 相位解包裹之前先看包裹相位 phase_wrapped np.angle(reconstructed) amp np.abs(reconstructed)这一步做完重建相位应该已经看不到密集的载频条纹高斯凸起形状清晰可辨。掩膜半径代表物体空间带宽的 1.5 倍这个系数不能随意加大——加大会把零级项的边缘也圈进来导致重建像叠上一层缓慢变化的背景。滤波后复振幅的振幅项和相位项分别对应样品的吸收信息和光程差信息这就是数字全息实验的最终输出。先在模拟数据上调通滤波参数再上实验台我个人的经验是至少能省掉一半的调试时间。4. 实验台上采集数字全息图的关键参数4.1 一套可复用的最小光路模拟验证通过之后下一步就是在光学平台上搭真实光路。最常见的数字全息实验光路是马赫-曾德尔式离轴结构激光经分束器分成两路一路经过样品形成物光另一路经反射镜偏转一定角度作为参考光两路在分束器合束后在相机靶面干涉。光源用单纵模激光器常见的是 532 nm 固体激光器或 633 nm 氦氖激光器关键指标是相干长度。所谓相干长度就是参考光和物光的光程差必须控制在这个长度以内才能形成清晰条纹。单纵模激光器的相干长度通常在厘米到米量级光路差个几厘米问题不大如果是多模激光二极管相干长度只有几百微米光路稍微调偏一点条纹就消失了。相机方面任何带有全局快门、像素尺寸已知的工业相机都可以用。需要记下两个参数像素尺寸 Δx 和像素数 N。它们决定了离轴角的上限和重建视场大小。做了这么多数字全息实验我的习惯是每次实验前先把λ / (2Δx)算出来写在实验记录本上调整参考光角度时用这个值作为上限参考。4.2 参考光夹角、强度比与光程差参考光夹角直接影响条纹密度调整时用分束器或反射镜的角度旋钮控制。判断标准很简单在相机预览界面上数条纹。条纹太稀一个视场内不到 20 条频谱分离不干净条纹太密接近像素尺寸的 2 倍采样开始混叠。中间状态需要慢慢找。物参光强度比是另一个容易被忽略的参数。干涉条纹的对比度 V 2√(I_obj·I_ref) / (I_obj I_ref)当物光与参考光强度相等时 V1条纹最清晰。实际样品透过的光强通常远小于参考光所以要在参考光路加中性密度衰减片。一个实用的做法是挡住物光单独看参考光强度再挡住参考光单独看物光强度调整衰减片让两者读数接近。相机靶面避免过曝建议让最大灰度值控制在满量程的 70% 左右给干涉条纹留出调制空间。光程差的影响在激光光源下通常不敏感但如果是低相干光源要用等光程原则搭光路。测量光程差可以用一把卷尺量物理路径长度精度要求约在相干长度的一半以内。4.3 采集时的环境震动与暗场处理数字全息实验对震动极其敏感。光学平台的台面在加载重物后需要重新认水平相机建议用刚性支架固定不要用手触碰台面。曝光时间设置要综合考虑条纹对比度和震动曝光时间太长震动会让条纹模糊太短则光子噪声增大。一般 1 ms 到 10 ms 是一个合理区间。正式采集前还要拍两组参考帧一是完全挡住激光后采集的暗场帧用来扣除相机暗电流和背景偏置二是挡住物光、只留参考光的参考帧用于后续去除背景条纹。重建时先用原始全息图减去暗场帧再做归一化处理。这一步对相位结果的稳定性影响很大。# 采集参数记录示例实验记录本格式 # wavelength: 532nm # pixel_size: 3.45um # NxN: 1024x1024 # exposure: 3ms # theta: 约2.5度目测每毫米约30条条纹 # 物参比: 1:1.2 # 暗场帧: 已采集曝光3ms快门全闭 # 参考光帧: 已采集物光遮挡实验数据的处理流程和模拟数据基本一致读入 tif 或 raw 文件 → 减暗场 → 与参考帧归一化 → 傅里叶变换 → 频域滤波 → 角谱传播。真实数据与模拟数据的最大区别在于噪声更重、频谱边带边缘不干净、相位中存在由散斑引起的随机跳变。处理这些问题的具体方法就是下一章的重点。5. 重建参数与相位解包裹的实战排错5.1 真实全息图的预处理顺序拿到真实采集的全息图后第一步不是重建而是把采集时引入的系统性误差清理掉。完整顺序是先减暗场帧消除固定模式噪声再逐像素除以参考光帧的光强分布消除照明不均匀性最后做归一化使全息图均值落在 0 到 1 的范围内。这个步骤的顺序不能换。先减暗场再归一化是把加性噪声和乘性噪声分开处理的标准做法。如果暗场帧质量不好可以用多帧暗场取平均或者用一帧全息图的四个角区域估算背景值——但前提是物体不出现在图像边缘。5.2 频谱滤波在真实数据里的参数调整模拟数据中边带中心位置是精确已知的真实数据则需要从频谱图里自己找。做法是对预处理后的全息图做二维傅里叶变换把频谱用对数坐标显示出来边带表现为零频两侧的一对亮斑。找到亮斑中心的坐标用它替代模拟代码里的 center_pix_x。真实频谱的边带通常比模拟数据宽而且零级项的边缘可能会和边带粘连。这时圆形掩膜的半径需要手动微调。沿着频率轴看幅度剖面找到边带和零级项之间的鞍点位置半径取鞍点和边带中心距离的 90%。这个值在不同样品之间差别很大纯相位样品衍射弱带宽窄结构复杂的强散射样品衍射角大掩膜半径要大得多。频域滤波后还会残留零级项泄漏具体表现为重建相位上叠加一层缓慢变化的背景倾斜。修正方法是用物体区域外的相位值拟合一个二维平面然后从整个相位图中减去这个平面。物体区域怎么找振幅图上物体的阴影通常能提供一个大致的掩膜。5.3 相位解包裹为什么是最容易翻车的一步数字全息实验重建得到的相位是缠绕相位因为 atan2 的输出范围只有 (−π, π]超过这个范围会自动跳变。把跳变还原成连续相位分布的过程叫相位解包裹。一维情况很好处理沿着路径逐个加上 2π 的整数倍二维就难了因为不存在一条能覆盖整幅图像的全局最优路径——残差点残差点让相位数据变成多值函数。残差点定义如下绕某个 2×2 的像素方格一周对相邻四个相位差求和。如果差值不为 0这个方格对应的中心就是一个残差点。残差点的存在意味着从不同方向积分会得到不一致的结果。实验中散斑噪声、低信噪比区域、欠采样条纹都会大量产生残差点这是真实数据和模拟数据最大的差异所在。5.3.1 用 skimage 做快速解包裹如果残差点密度不高用现成的最小二乘类算法最快。Python 的 scikit-image 提供了质量导向解包裹的实现from skimage.restoration import unwrap_phase # phase_wrapped 是 atan2 得到的缠绕相位范围在 [-pi, pi) phase_unwrapped unwrap_phase(phase_wrapped, seed0) # 检查跳变是否消除 jumps np.sum(np.abs(np.diff(phase_unwrapped, axis0)) np.pi) print(f残留跳变像素数: {jumps})unwrap_phase 内部实现的是加权最小二乘类算法seed 参数控制随机种子影响残差点较少时的一致性。需要说明的是最小二乘法在残差点密集的区域会把误差平滑扩散表现为相位图上的“气泡”状失真。如果发现这种情况说明样本本身的相位梯度过大或信噪比太差需要回到采集环节而不是继续调算法。5.3.2 残差点质量图与掩膜策略工业级实验里更常用的是质量图导向的路径跟踪法。提前算出一幅质量图比如用相位梯度倒数或振幅作为质量指标然后从高质量区域开始逐步向低质量区域增长。处理代码通常要自己写核心是一个优先队列import heapq def quality_guided_unwrap(phase, quality): 质量图导向解包裹 phase: 缠绕相位 quality: 质量图值越大代表质量越高 h, w phase.shape unwrapped np.zeros_like(phase) visited np.zeros_like(phase, dtypebool) # 从质量最高的点开始 start np.unravel_index(np.argmax(quality), phase.shape) unwrapped[start] phase[start] visited[start] True heap [] for dy, dx in [(-1,0),(1,0),(0,-1),(0,1)]: ny, nx start[0]dy, start[1]dx if 0 ny h and 0 nx w and not visited[ny, nx]: delta phase[ny, nx] - phase[start[0], start[1]] delta_wrapped np.mod(delta np.pi, 2*np.pi) - np.pi unwrapped[ny, nx] unwrapped[start] delta_wrapped heapq.heappush(heap, (-quality[ny, nx], ny, nx)) visited[ny, nx] True while heap: _, cy, cx heapq.heappop(heap) for dy, dx in [(-1,0),(1,0),(0,-1),(0,1)]: ny, nx cydy, cxdx if 0 ny h and 0 nx w and not visited[ny, nx]: delta phase[ny, nx] - phase[cy, cx] delta_wrapped np.mod(delta np.pi, 2*np.pi) - np.pi unwrapped[ny, nx] unwrapped[cy, cx] delta_wrapped heapq.heappush(heap, (-quality[ny, nx], ny, nx)) visited[ny, nx] True return unwrapped这个实现的关键有两点一是所有相邻相位差不直接相加而是先包裹到 (−π, π] 区间再加这样能防止误差沿路径累积二是优先队列保证高质量区域先被访问残差点通常落在质量低的位置所以最后才被处理对周围区域的污染被限制住了。质量图可以选振幅图、相位梯度倒数或二者的乘积。纯相位样品建议用振幅作为质量图因为振幅信息不受相位跳变影响。6. 让重建结果更清晰的三个进阶技巧6.1 用数值重聚焦确定最佳重建距离相机记录的物体位置存在误差直接用卷尺量的 z 值重建出来的图像常常是模糊的。数字全息实验有个天然优势不需要机械移动样品只需要在重建阶段扫描不同的 z 值并计算聚焦评价函数就能找到最佳像面。常用评价函数包括图像梯度平方和、频谱高频能量占比、振幅图的稀疏度如 Tamura 系数。下面是一个极简的自动对焦实现def tamura_coefficient(amplitude): 用振幅图的统计特性评价聚焦程度 std np.std(amplitude) mean np.mean(amplitude) return np.sqrt(std) / mean # z 扫描范围以粗略距离为中心 ±5mm z_candidates np.linspace(z - 0.005, z 0.005, 101) scores [] for zc in z_candidates: U angular_spectrum_propagation(object_wave, wavelength, pixel_size, zc) scores.append(tamura_coefficient(np.abs(U))) best_z z_candidates[np.argmax(scores)]Tamura 系数对聚焦状态敏感的原因是聚焦良好时图像细节锐利、灰度分布离散程度高离焦时不同结构的能量被抹平灰度分布趋于集中。这个评价函数在样品是纯相位物体时最可靠如果是强吸收样品用梯度平方和更稳。6.2 共轭像和零级像的进一步压制离轴设计已经分离了三个级次但滤波后的边带还是可能混入零级项残余。一个工程技巧是在预处理阶段就减去参考光帧让全息图的直流分量大幅下降再做频域滤波时零级项能量显著减弱。另外如果系统允许调节参考光相位可以采集四幅相移全息图做四步相移平均从算法层面消掉零级项和共轭像。代价是需要额外的硬件控制收益是重建像的信噪比通常能提升一个量级。6.3 散斑噪声的抑制激光照明下粗糙表面的物光会携带大量散斑直接导致相位图出现高频随机噪声。常见做法是角度复用或频率复用采集多幅微弱不同的参考光角度比如调整参考光反射镜的压电陶瓷然后对重建的振幅和相位分别求平均。如果硬件不允许也可以在重建后用小窗口中值滤波做相位图的平滑但要注意中值滤波窗口不要超过 3×3否则会把真实的相位梯度抹掉。这一套流程走下来数字全息实验从采集到重建再到相位解包裹的基本功就齐了。本文还有配套的精品资源点击获取
返回列表