数字全息实验全流程:干涉记录、数值重建与相位解包裹实战指南
2026/9/12 23:05:34 网站建设 项目流程

简介:数字全息实验涉及干涉记录与数值重建,本资源面向光学工程、信息光学方向的学生和科研人员,按照真实实验流程整理了一套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, d=pixel_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, d=pixel_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),当物光与参考光强度相等时 V=1,条纹最清晰。实际样品透过的光强通常远小于参考光,所以要在参考光路加中性密度衰减片。一个实用的做法是:挡住物光单独看参考光强度,再挡住参考光单独看物光强度,调整衰减片让两者读数接近。相机靶面避免过曝,建议让最大灰度值控制在满量程的 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, seed=0) # 检查跳变是否消除 jumps = np.sum(np.abs(np.diff(phase_unwrapped, axis=0)) > 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, dtype=bool) # 从质量最高的点开始 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 = cy+dy, cx+dx 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,否则会把真实的相位梯度抹掉。这一套流程走下来,数字全息实验从采集到重建再到相位解包裹的基本功就齐了。

本文还有配套的精品资源,点击获取

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

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

立即咨询