Gerchberg-Saxton (GS) 和混合输入输出(Hybrid Input-Output, HIO)算法

1. 简介

Gerchberg-Saxton (GS) 算法是一种常用于相位恢复和光学成像的迭代算法。该算法最初由R.W. Gerchberg和W.O. Saxton于1972年提出 [1],主要用于从强度测量数据中恢复相位信息。以下是该算法的基本步骤:

  1. 初始化:
    • 准备输入图像的幅度信息(通常是从实验数据中获得的强度图像,取其平方根得到幅度)。
    • 初始化相位信息,通常可以设置为随机相位或者全零相位。
  2. 频域迭代:
    • 对当前的图像(包含初始相位信息)进行傅里叶变换,得到频域图像。
    • 用实验测得的频域幅值替换频域图像的幅度,保留原相位信息。
    • 对替换后的频域图像进行逆傅里叶变换,回到空间域。
  3. 空间域迭代:
    • 用实验测得的空间域幅值替换空间域图像的幅度,保留逆傅里叶变换后得到的相位信息。
    • 将更新后的图像再次进行傅里叶变换,进入下一次迭代。
  4. 收敛判断:
    • 判断相位是否收敛,即相位变化是否在一定阈值范围内。
    • 如果达到收敛条件,则输出最终的相位信息;否则,返回步骤2继续迭代。

2. 算法描述

输入:

  • ∣ x [ n , m ] ∣ | x[ n, m] | x[n,m]:空间域的幅度信息
  • ∣ X [ k , l ] ∣ | X[ k, l] | X[k,l]​: 频域的幅度信息
  • ϵ \epsilon ϵ:误差阈值

输出:

  • z [ n , m ] z[n,m] z[n,m] -满足以下幅度约束的二维数组,即: ∣ z [ n , m ] ∣ = ∣ x [ n , m ] ∣ |z[n,m]|=|x[n,m]| z[n,m]=x[n,m] ∣ Z [ k , l ] ∣ = ∣ X [ k , l ] ∣ |Z[k,l]|=|X[k,l]| Z[k,l]=X[k,l], 其中 Z [ k , l ] Z[k,l] Z[k,l] z [ n , m ] z[n,m] z[n,m] 的离散傅里叶变换(DFT)。

初始化:

  • 选择初始 z 0 [ n , m ] = ∣ x [ n , m ] ∣ exp ⁡ ( j ϕ [ n , m ] ) z_0[n,m]=|x[n,m]|\exp(j\phi[n,m]) z0[n,m]=x[n,m]exp(jϕ[n,m]) (例如,使用随机相位 ϕ [ n , m ] \phi[n,m] ϕ[n,m])。

一般步骤 (第 i i i次迭代, i = 1 , 2 , … ) i=1,2,\ldots) i=1,2,)

  1. ​ 对 z i [ n , m ] z_i[n,m] zi[n,m] 进行二维傅里叶变换,得到 Z i [ k , l ] Z_i[k,l] Zi[k,l]

  2. ​ 保持当前傅里叶相位不变,但施加频域幅度约束: Z i ′ [ k , l ] = ∣ X [ k , l ] ∣ ⋅ Z i [ k , l ] / ∣ Z i [ k , l ] ∣ Z_i^{\prime}[k,l]=|X[k,l]|\cdot Z_i[k,l]/|Z_i[k,l]| Zi[k,l]=X[k,l]Zi[k,l]/∣Zi[k,l]

  3. ​ 对 Z i ′ [ k , l ] Z_i^{\prime}[k,l] Zi[k,l]进行二维逆傅里叶变换,得到 z i ′ [ n , m ] z_i^{\prime}[n,m] zi[n,m]

  4. ​ 保持当前空间相位不变,但施加空间域幅度约束: z i + 1 [ n , m ] = ∣ x [ n , m ] ∣ ⋅ z i ′ [ n , m ] / ∣ z i ′ [ n , m ] ∣ 。 z_{i+1}[n,m]=|x[n,m]|\cdot z_i'[n,m]/|z_i'[n,m]|\text{。} zi+1[n,m]=x[n,m]zi[n,m]/∣zi[n,m]

  5. ​ 回到步骤1。

终止条件:直到误差
E i = ∑ k , l ∥ ∣ Z i [ k , l ] ∣ − ∣ X [ k , l ] ∣ ∥ 2 ≤ ϵ E_i=\sum_{k,l}\left\|\left|Z_i[k,l]\right|-\left|X[k,l]\right|\right\|^2\leq\epsilon Ei=k,lZi[k,l]X[k,l]2ϵ

3. 混合输入输出(Hybrid Input-Output, HIO)算法

​ 混合输入输出(Hybrid Input-Output, HIO)算法是Gerchberg-Saxton (GS) 算法的一种改进版本,用于加快相位恢复的收敛速度,并解决GS算法容易陷入局部最优解的问题。HIO算法由Fienup于1982年提出 [2],通过在迭代过程中引入一种新颖的更新策略,改善了相位恢复的性能。

3.1 HIO算法步骤

  1. 初始化:

    • 与GS算法相同,准备输入图像的幅度信息和初始相位信息(随机相位或全零相位)。
  2. 频域迭代:

    • 对当前的图像(包含当前相位信息)进行傅里叶变换,得到频域图像。
    • 用实验测得的频域幅值替换频域图像的幅度,保留原相位信息。
    • 对替换后的频域图像进行逆傅里叶变换,回到空间域。
  3. 空间域更新:

    • 使用以下更新公式对空间域图像进行修正:
      z n + 1 ( x ) = { z ( x ) if  x ∈ Ω z n ( x ) − β z ( x ) if  x ∉ Ω z_{n+1}(x)=\begin{cases}z(x)&\text{if}\ x\in\Omega\\z_n(x)-\beta z(x)&\text{if}\ x\notin\Omega\end{cases} zn+1(x)={z(x)zn(x)βz(x)if xΩif x/Ω
      其中, z ( x ) z(x) z(x) 是逆傅里叶变换后的图像, z n ( x ) z_n(x) zn(x) 是上一次迭代的图像, β \beta β 是一个控制参数,通常取值在0.5到1之间, Ω \Omega Ω 是已知幅值信息的区域。
  4. 收敛判断:

    • 判断相位是否收敛,即相位变化是否在一定阈值范围内。
    • 如果达到收敛条件,则输出最终的相位信息;否则,返回步骤2继续迭代。

3.2 HIO算法的优势

  1. 更快的收敛速度:HIO算法通过引入混合输入输出的更新策略,有效避免了GS算法的局部最优解问题,通常能够更快地收敛到全局最优解。
  2. 更好的鲁棒性:由于HIO算法可以在不满足约束条件的区域进行负反馈修正,因此在处理复杂相位恢复问题时表现更为稳定。

3.3 算法描述

输入:

  • ∣ x [ n , m ] ∣ | x[ n, m] | x[n,m]:空间域的幅度信息
  • ∣ X [ k , l ] ∣ | X[ k, l] | X[k,l]: 频域的幅度信息
  • ϵ \epsilon ϵ:误差阈值
  • β \beta β :HIO算法的反馈参数

输出:

  • z [ n , m ] z[n,m] z[n,m] - 满足以下幅度约束的二维数组,即: ∣ z [ n , m ] ∣ = ∣ x [ n , m ] ∣ |z[n,m]|=|x[n,m]| z[n,m]=x[n,m] ∣ Z [ k , l ] ∣ = ∣ X [ k , l ] ∣ |Z[k,l]|=|X[k,l]| Z[k,l]=X[k,l], 其中 Z [ k , l ] Z[k,l] Z[k,l] z [ n , m ] z[n,m] z[n,m] 的离散傅里叶变换(DFT)。

初始化:

  • 选择初始 z 0 [ n , m ] = ∣ x [ n , m ] ∣ exp ⁡ ( j ϕ [ n , m ] ) z_0[n,m]=|x[n,m]|\exp(j\phi[n,m]) z0[n,m]=x[n,m]exp(jϕ[n,m]) (例如,使用随机相位 ϕ [ n , m ] \phi[n,m] ϕ[n,m])。

一般步骤 (第 i i i次迭代, i = 1 , 2 , … ) : i=1,2,\ldots): i=1,2,):

  1. z i [ n , m ] z_i[n,m] zi[n,m]进行二维傅里叶变换,得到 Z i [ k , l ] Z_i[k,l] Zi[k,l]

  2. 保持当前傅里叶相位不变,但施加频域幅度约束: Z i ′ [ k , l ] = ∣ X [ k , l ] ∣ ⋅ Z i [ k , l ] / ∣ Z i [ k , l ] ∣ Z_i^{\prime}[k,l]=|X[k,l]|\cdot Z_i[k,l]/|Z_i[k,l]| Zi[k,l]=X[k,l]Zi[k,l]/∣Zi[k,l]

  3. Z i ′ [ k , l ] Z_i^{\prime}[k,l] Zi[k,l]进行二维逆傅里叶变换,得到 z i ′ [ n , m ] z_i^{\prime}[n,m] zi[n,m]

  4. 保持当前空间相位不变,但施加空间域幅度约束,且对不满足约束的区域进行反馈修正:
    z i + 1 [ n , m ] = { ∣ x [ n , m ] ∣ ⋅ z i ′ [ n , m ] / ∣ z i ′ [ n , m ] ∣ if ∣ x [ n , m ] ∣ ≠ 0 z i [ n , m ] − β z i ′ [ n , m ] if ∣ x [ n , m ] ∣ = 0 z_{i+1}[n,m]=\begin{cases}|x[n,m]|\cdot z_i'[n,m]/|z_i'[n,m]|&\text{if}|x[n,m]|\neq0\\z_i[n,m]-\beta z_i'[n,m]&\text{if}|x[n,m]|=0\end{cases} zi+1[n,m]={x[n,m]zi[n,m]/∣zi[n,m]zi[n,m]βzi[n,m]ifx[n,m]=0ifx[n,m]=0

  5. 回到步骤1。

终止条件:直到误差
E i = ∑ k , l ∥ ∣ Z i [ k , l ] ∣ − ∣ X [ k , l ] ∣ ∥ 2 ≤ ϵ E_i=\sum_{k,l}\||Z_i[k,l]|-|X[k,l]|\|^2\leq\epsilon Ei=k,l∥∣Zi[k,l]X[k,l]2ϵ

4. 算法实现与对比

import numpy as np
import matplotlib.pyplot as plt
from skimage.data import camera, checkerboard
from skimage.transform import resize

# 加载skimage库中的示例图像
amplitude_image = camera()
phase_image = checkerboard()

# 如果振幅图像和相位图像的大小不同,调整相位图像的大小
if amplitude_image.shape != phase_image.shape:
    phase_image = resize(phase_image, amplitude_image.shape, anti_aliasing=True)

# 对振幅和相位图像进行填充
padding_width = 50
amplitude_image = np.pad(amplitude_image, pad_width=padding_width, mode='constant', constant_values=0)
phase_image = np.pad(phase_image, pad_width=padding_width, mode='constant', constant_values=0)

# 将图像归一化到[0, 1]范围内
amplitude_image = amplitude_image / np.max(amplitude_image)
phase_image = phase_image / np.max(phase_image)

# 生成复数对象
complex_obj = amplitude_image * np.exp(1j * phase_image)

# 进行傅里叶变换
ft_obj = np.fft.fft2(complex_obj)
abs_ft_obj = np.abs(ft_obj)

# 初始化相位图像
initial_phase = np.angle(np.exp(1j * np.random.rand(*amplitude_image.shape)))


# Gerchberg-Saxton (GS) 算法
def gerchberg_saxton(amplitude, initial_phase, num_iterations, epsilon):
    z = amplitude * np.exp(1j * initial_phase)
    errors = []
    for i in range(num_iterations):
        # 正向傅里叶变换
        Z = np.fft.fft2(z)

        # 计算误差并检查终止条件
        error = np.sum((np.abs(Z) - abs_ft_obj) ** 2)
        errors.append(error)
        if error <= epsilon:
            print(f'GS algorithm converged after {i + 1} iterations with error {error:.6f}')
            break

        # 在傅里叶空间中施加振幅约束
        Z = abs_ft_obj * Z / np.abs(Z)
        # 逆傅里叶变换
        z_prime = np.fft.ifft2(Z)
        # 在实空间中施加振幅约束
        z = amplitude * z_prime / np.abs(z_prime)

    final_phase = np.angle(z)
    return final_phase, errors


# Hybrid Input-Output (HIO) 算法
def hio(amplitude, initial_phase, num_iterations, beta, epsilon):
    z = amplitude * np.exp(1j * initial_phase)
    errors = []
    for i in range(num_iterations):
        # 正向傅里叶变换
        Z = np.fft.fft2(z)

        # 计算误差并检查终止条件
        error = np.sum((np.abs(Z) - abs_ft_obj) ** 2)
        errors.append(error)
        if error <= epsilon:
            print(f'HIO algorithm converged after {i + 1} iterations with error {error:.6f}')
            break

        # 在傅里叶空间中施加振幅约束
        Z = abs_ft_obj * Z / np.abs(Z)
        # 逆傅里叶变换
        z_prime = np.fft.ifft2(Z)
        # 在实空间中施加振幅约束,并引入反馈机制
        mask = (amplitude != 0)
        z = np.where(mask,
                     amplitude * z_prime / np.abs(z_prime),
                     z - beta * z_prime)

    final_phase = np.angle(z)
    return final_phase, errors


# 参数设置
num_iterations = 50
beta = 0.9
epsilon = 1e-6

# 应用GS算法
gs_phase, gs_errors = gerchberg_saxton(amplitude_image, initial_phase, num_iterations, epsilon)

# 应用HIO算法
hio_phase, hio_errors = hio(amplitude_image, initial_phase, num_iterations, beta, epsilon)

# 设置绘图的字体和字号
font = {'family': 'serif',
        'weight': 'normal',
        'size': 20}
plt.rc('font', **font)

# 显示结果
plt.figure(figsize=(12, 6))

plt.subplot(1, 3, 1)
plt.title('Original Phase')
plt.imshow(phase_image, cmap='gray')
plt.axis('off')

plt.subplot(1, 3, 2)
plt.title('GS Phase')
plt.imshow(gs_phase, cmap='gray')
plt.axis('off')

plt.subplot(1, 3, 3)
plt.title('HIO Phase')
plt.imshow(hio_phase, cmap='gray')
plt.axis('off')

plt.tight_layout()
plt.show()


# 绘制误差下降曲线
plt.figure(figsize=(12, 6))
plt.plot(gs_errors, label='GS Errors')
plt.plot(hio_errors, label='HIO Errors')
plt.xlabel('Iteration')
plt.ylabel('Error')
plt.yscale('log')
plt.title('Error Convergence')
plt.legend()
plt.show()

循环50次的结果对比如下:

在这里插入图片描述

在这里插入图片描述

5. 总结

GS算法和HIO算法都是相位检索的有效方法,各有优缺点。GS算法简单易实现,但在复杂情况下收敛较慢且易陷入局部极小值。HIO算法通过引入反馈机制加速收敛,并增强鲁棒性,但其实现相对复杂且对参数选择敏感。在实际应用中,可以根据具体问题的需求选择合适的算法,或者结合两种算法的优点进行混合使用。

参考文献

  1. R. Gerchberg and W. Saxton, “A practical algorithm for the determination of phase from image and diffraction plane pictures,” Optik, vol. 35, p. 237, 1972.
  2. Fienup J R. Phase retrieval algorithms: a comparison[J]. Applied optics, 1982, 21(15): 2758-2769.
  • 23
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
HIO-ER(Hybrid Input-Output with Error Reduction)是一种常用的相位恢复算法,用于从幅度信息中恢复出物体的相位信息。以下是一个简单的HIO-ER算法的示例代码: ```python import numpy as np def hio_er_algorithm(amplitude, support, max_iterations=1000, beta=0.9, threshold=0.01): n = len(amplitude) phase = np.random.rand(n) * 2 * np.pi # 初始化相位 for iteration in range(max_iterations): previous_phase = phase.copy() # 计算复振幅 complex_amplitude = amplitude * np.exp(1j * phase) # Fourier变换 fourier_transform = np.fft.fftshift(np.fft.fft(complex_amplitude)) # 保留幅度信息,重构相位 fourier_transform = amplitude * np.exp(1j * np.angle(fourier_transform)) # 逆Fourier变换 inverse_transform = np.fft.ifft(np.fft.ifftshift(fourier_transform)) # 更新相位 phase = np.angle(inverse_transform) # 限制相位在支持内部 phase[support == 0] = previous_phase[support == 0] # 错误减小步骤 phase_error = np.angle(inverse_transform / amplitude) phase_error[support == 0] = 0 phase -= beta * phase_error # 判断收敛条件 if np.max(np.abs(phase - previous_phase)) < threshold: break return phase ``` 在这个示例代码中,`amplitude` 是物体的幅度信息,`support` 是物体的支持信息(即物体的形状或位置信息),`max_iterations` 是最大迭代次数,`beta` 是错误减小步骤的参数,`threshold` 是收敛条件的阈值。 该算法的基本思想是通过交替更新幅度和相位来逐步恢复物体的相位信息。在每次迭代中,根据当前的相位估计计算出复振幅,然后根据幅度信息重构相位,并进行逆Fourier变换得到物体的估计。然后更新相位,限制相位在支持内部,并进行错误减小步骤以减小相位估计中的错误。重复以上步骤直到收敛。 需要注意的是,实际应用中可能需要根据具体问题进行一些调整和修改。此代码仅提供了一个简单的示例供参考。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xy_optics

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值