3. 直接斜率法波前重构

直接斜率法波前重构 学习卡片

任务定义

本案例实现基于 Shack-Hartmann 波前传感器测量数据的直接斜率法波前重构。输入为子孔径内波前斜率(x、y 方向),输出为离散采样点上的波前相位分布。采用 zonal 重构策略:将波前相位建模为子孔径网格节点上的未知量,利用相邻节点间的相位差与测量斜率之间的线性关系建立方程组,通过最小二乘求解得到波前相位。

算法原理与实现

设子孔径按 M×N 网格排列,节点数为 (M+1)×(N+1)。x 方向斜率测量值对应水平相邻节点间的相位差除以子孔径间距 d,y 方向同理。构建稀疏矩阵 A(尺寸 2MN × (M+1)(N+1)),每行对应一个斜率测量方程,未知量为各节点相位。由于整体平移不影响斜率,需固定一个参考节点相位为 0 以保证解唯一。采用稀疏最小二乘求解。

import numpy as np
from scipy.sparse import lil_matrix
from scipy.sparse.linalg import lsqr

def direct_slope_reconstruction(slope_x, slope_y, d=1.0):
    """
    直接斜率法波前重构 (zonal)
    参数:
        slope_x: 形状 (M, N) 的 x方向斜率 (每子孔径)
        slope_y: 形状 (M, N) 的 y方向斜率
        d: 子孔径间距
    返回:
        phase: 形状 (M+1, N+1) 的节点相位
    """
    M, N = slope_x.shape
    n_nodes = (M+1) * (N+1)
    n_eq = 2 * M * N + 1  # +1 为参考节点约束

    A = lil_matrix((n_eq, n_nodes))
    b = np.zeros(n_eq)

    row = 0
    # x方向斜率: 水平相邻节点差 / d = slope_x
    for i in range(M):
        for j in range(N):
            node_left = i * (N+1) + j
            node_right = i * (N+1) + (j+1)
            A[row, node_left] = -1.0 / d
            A[row, node_right] = 1.0 / d
            b[row] = slope_x[i, j]
            row += 1

    # y方向斜率: 垂直相邻节点差 / d = slope_y
    for i in range(M):
        for j in range(N):
            node_bottom = i * (N+1) + j
            node_top = (i+1) * (N+1) + j
            A[row, node_bottom] = -1.0 / d
            A[row, node_top] = 1.0 / d
            b[row] = slope_y[i, j]
            row += 1

    # 固定参考节点 (0,0) 相位为 0
    A[row, 0] = 1.0
    b[row] = 0.0

    A = A.tocsr()
    phase_flat, _ = lsqr(A, b, atol=1e-10, btol=1e-10)[:2]
    return phase_flat.reshape((M+1, N+1))

测试与验证

构造已知相位分布 phi(x,y) = 0.5x² + 0.3y²,在 4×4 子孔径网格上解析计算各子孔径中心处的斜率(中心差分),作为输入进行重构,并与原始相位比较。

# 生成测试数据
M, N = 4, 4
d = 1.0
x = np.linspace(-2, 2, N+1)
y = np.linspace(-2, 2, M+1)
X, Y = np.meshgrid(x, y)
true_phase = 0.5*X**2 + 0.3*Y**2

# 子孔径中心坐标
xc = (x[:-1] + x[1:]) / 2
yc = (y[:-1] + y[1:]) / 2
Xc, Yc = np.meshgrid(xc, yc)

# 解析斜率
slope_x = Xc          # d/dx (0.5x^2) = x
slope_y = 0.6 * Yc    # d/dy (0.3y^2) = 0.6y

# 重构
recon_phase = direct_slope_reconstruction(slope_x, slope_y, d)

# 误差评估(去除整体平移)
recon_phase = recon_phase - recon_phase[0,0]
true_phase = true_phase - true_phase[0,0]
rmse = np.sqrt(np.mean((recon_phase - true_phase)**2))
print(f"重构 RMSE: {rmse:.2e}")

预期输出:RMSE 在 1e-10 量级(因解析斜率与离散差分模型完全匹配,重构精度仅受数值求解器容差限制)。

验证方法

运行上述代码,观察终端输出的 RMSE 值。若 RMSE < 1e-8,说明重构算法正确实现了斜率到相位的映射;若误差较大,检查子孔径索引映射与符号约定是否正确。

判定标准:重构相位与真实相位(去除整体平移后)的 RMSE 小于 1e-8,即判定通过。
直接斜率法波前重构数据流 SH 传感器 斜率 s_x, s_y (M×N 子孔径) 稀疏矩阵构建 A·φ = b (2MN+1) × (M+1)(N+1) 参考节点约束 最小二乘求解 scipy.sparse.lsqr 稀疏 QR 分解 波前相位 φ (M+1)×(N+1) 节点 验证 与解析相位比较 RMSE 输入 处理 求解 输出 验证

关键说明

  • 本实现适用于子孔径斜率数据完整、无缺失的情况;若存在坏点需先插值或引入加权处理。
  • 参考节点选择 (0,0) 处节点,消除重构波前的整体平移不确定性,不影响波前形状。
  • 矩阵规模为 (2MN+1) × (M+1)(N+1),对典型 20×20 子孔径约 800×441,稀疏求解效率高。