3. OCT光谱重采样
为什么波长域均匀采样在FFT中会出错
OCT光谱仪采集到的干涉光谱,其采样点在波长域近似均匀(例如线阵相机像素按λ等间隔分布),但FFT要求信号在波数域(k = 2π/λ)均匀采样。由于k与λ是非线性关系,波长域等间隔采样映射到k域后变成非均匀采样,直接FFT会产生严重的点扩散函数展宽和伪影。重采样的任务就是:利用标定得到的波长-波数映射,把非均匀k采样的光谱插值到均匀k网格上。
标定映射的获取与重采样实现
重采样的前提是已知每个像素对应的波长λi,由此计算ki=2π/λi。标定方法通常有两种:
- 光谱仪标定法:用已知谱线的光源(如汞氩灯)照射光谱仪,记录各谱线在相机上的像素位置,拟合像素-波长多项式。
- 扫频源标定法:用马赫-曾德尔干涉仪产生等频率间隔的时钟信号,直接得到k域均匀采样。
得到ki后,构建均匀k网格kuniform,从kmin到kmax等间隔取N个点,然后对原始光谱I(λi)在kuniform上插值。
Python实现:线性插值重采样
import numpy as np
# 1. 标定数据:像素索引 → 波长(示例:多项式拟合系数)
# 假设已通过谱线标定得到 λ(p) = a0 + a1*p + a2*p²
pixel = np.arange(2048) # 2048像素线阵相机
a0, a1, a2 = 780.0, 0.045, -1.2e-7 # 示例系数,单位nm
wavelength = a0 + a1*pixel + a2*pixel**2 # nm
# 2. 波长 → 波数(k = 2π/λ,单位rad/nm)
k = 2*np.pi / wavelength # 注意:k随像素增大而增大(λ减小)
# 3. 读取原始光谱干涉信号(示例:模拟信号)
# 实际中从文件读取,此处用高斯调制余弦模拟
I_lambda = 1.0 + 0.8*np.cos(2*np.pi*0.02*pixel) * np.exp(-((pixel-1024)/600)**2)
# 4. 构建均匀k网格
k_min, k_max = k[0], k[-1]
N = len(pixel)
k_uniform = np.linspace(k_min, k_max, N)
# 5. 线性插值重采样
I_k = np.interp(k_uniform, k, I_lambda)
# 6. 验证:检查k_uniform是否等间隔
dk = np.diff(k_uniform)
print(f"k均匀性检查: max(dk)-min(dk) = {dk.max()-dk.min():.2e} (应接近0)")
print(f"原始k非均匀性: max(dk)-min(dk) = {np.diff(k).max()-np.diff(k).min():.2e}")
关键点:k = 2π/λ 中,当λ从大到小变化时,k从小到大变化。因此k数组是单调递增的,可以直接用于np.interp。如果标定得到的k不是单调的,需要先排序。
重采样效果验证
重采样后,应对I(k)做FFT得到A-scan,观察点扩散函数(PSF)的展宽是否被消除。验证方法:
- 对重采样前后的信号分别做FFT,比较PSF的-6dB宽度。
- 重采样后PSF应更窄、旁瓣更低,展宽伪影明显减弱。
- 若重采样后PSF反而变差,检查k网格范围是否覆盖了原始k的全部区间,以及插值是否引入了边界外推。
常见陷阱:如果k_uniform的范围超出了原始k的范围(k_min, k_max),np.interp会进行边界外推(默认用端点值填充),导致边缘伪影。应确保k_uniform严格落在[k_min, k_max]内,或对超出部分做截断处理。
重采样参数速查表
| 参数 | 含义 | 典型值/建议 |
|---|---|---|
| N | 重采样点数 | 等于原始像素数(如2048) |
| k_min | 波数下限 | 2π/λ_max |
| k_max | 波数上限 | 2π/λ_min |
| Δk | 波数间隔 | (k_max-k_min)/(N-1) |
| 插值方法 | 重采样算法 | 线性/三次样条/sinc |