我写了一个简短的matlab脚本文件,假设运行Fresnel的传播(衍射),这样给定一个输入字段U0,它会告诉你字段在距离z0之后的样子。我将结果与教科书结果进行了比较,看起来我的程序运行正常。问题是如果我尝试采取两个传播步骤而不是一个。即,不是采用程序的单次迭代来传播距离z0,而是采用程序的两次迭代来传播每个距离z0 / 2。然后我完全胡说八道,我无法弄清楚问题是什么。我们将非常感激地接受任何建议。 这是代码:
function U = fresnel_advance (U0, dx, dy, z, lambda)
% The function receives a field U0 at wavelength lambda
% and returns the field U after distance z, using the Fresnel
% approximation. dx, dy, are spatial resolution.
k=2*pi/lambda;
[ny, nx] = size(U0);
Lx = dx * nx;
Ly = dy * ny;
dfx = 1./Lx;
dfy = 1./Ly;
u = ones(nx,1)*((1:nx)-nx/2)*dfx;
v = ((1:ny)-ny/2)'*ones(1,ny)*dfy;
O = fftshift(fft2(U0));
H = exp(1i*k*z).*exp(-1i*pi*lambda*z*(u.^2+v.^2));
U = ifft2(O.*H);
答案 0 :(得分:3)
致电fft2
后,您也可以致电fftshift
将DC频率置于中间位置。
但是当你拨打ifft2
时,该功能假设你的DC频率仍为(1,1)。因此,在进行逆FFT之前,必须回到这种格式。
因此,将最后一行更改为U = ifft2(fftshift(O.*H))
可能会解决问题。
修改强>
我刚刚看到Matlab建议在ifftshift
insteaf两次fftshift
之后使用ifftshift
(无法找到引入它的版本)。根据文档,在奇数大小的情况下,调用序列ifftshift(fftshift(X))
和ifftshift(fftshift(X))
不相等。
所以我认为最好在代码的最后一步执行:U = ifft2(ifftshift(O.*H))
。
答案 1 :(得分:3)
实际上,问题出在您运行fft的方式上。在Fourier Optics and Computational Imaging by Khedar Kare, Wiley 2015中有很好的解释:
大多数编程平台中2D FFT的适当顺序,以使结果从物理上有意义 立场(例如描述衍射现象)因此 由fftshift(fft2(ifftshift(...)))给出。
在您的代码中,您应该:O = fftshift(fft2(ifftshift(U0)));
如果您对使用Python开发的软件感兴趣,有一个快速发展的Python工具箱,用于光学工具,包括衍射:PyOptica。在PyOptica中,可以使用以下方法传播波前:
import astropy.units as u
import numpy as np
import pyoptica as po
wavelength = 500 * u.nm
pixel_scale = 22 * u.um
npix = 1024
w = 6 * u.mm
h = 3 * u.mm
axis_unit = u.mm
wf = po.Wavefront(wavelength, pixel_scale, npix)
ap = po.RectangularAperture(w, h)
wf = wf * ap
fig_1 = po.plotting.plot_wavefront(wf, 'intensity', axis_unit=axis_unit)
第二步是传播:
f = 50 * u.cm
fs_f = po.FreeSpace(f)
wf_forward = wf * fs_f
fig_2 = po.plotting.plot_wavefront(wf_forward, 'intensity', axis_unit=axis_unit)
重要的是要记住菲涅耳传播的采样条件:
(z <= N(dx)^ 2 / lambda)其中:
该条件基于Computational Fourier Optics: A MATLAB Tutorial by David Voelz, SPIE 2011
您应该在代码中实现该条件。在PyOptica中,始终在传播之前对其进行检查;如果请求的距离违反条件,则将传播距离分解为子步骤。
答案 2 :(得分:2)
如果您可以向程序发布一些示例输入来演示问题,那将会很有帮助。
我怀疑这个问题可能与您没有足够时间调用FFTSHIFT这一事实有关。通常,人们认为光场矩阵的中心位于“原点”,而FFT2则考虑“左下角”。因此,您应该在FFT2之前以及之后使用FFTSHIFT。
你也需要对IFFT2作品做同样的事情。
修改的 为FFTSHIFT添加两个调用的理由:比较这两个:
N = 512; [x,y] = meshgrid(-1:1/N:(N-1)/N);
mask = (x.*x + y.*y) < 0.001;
figure(1)
imagesc(angle(fftshift(fft2(fftshift(mask)))))
figure(2)
imagesc(angle(fftshift(fft2(mask)))
答案 3 :(得分:0)
我认为相期有误。 “H = exp(1i k z)。 exp(-1i pi lambda z *(u。^ 2 + v。^ 2) );“ 应该 “H = exp(1i k z)。 exp(-1i pi / lambda / z *(u。^ 2 + v。^ 2));”