菲涅耳衍射分两步进行

时间:2014-01-07 12:42:40

标签: matlab physics propagation fresnel

我写了一个简短的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);  

4 个答案:

答案 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)

Initial aperture

第二步是传播:

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)

Results after propagation

重要的是要记住菲涅耳传播的采样条件: enter image description here(z <= N(dx)^ 2 / lambda)其中:

  • N-像素数(在一个方向上);
  • dx-像素大小;
  • λ-波长。

该条件基于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));”