有没有办法从np.fft2选择x/y输出轴的范围?我有一个计算孔径衍射图案的代码。孔径在2kx2k像素阵列中定义。衍射图基本上是孔径二维FT的内部部分。np.fft2给我一个输出数组,输入的大小相同,但x/y轴有一些预置的范围。当然,我可以通过使用图像查看器放大,但我已经失去了细节。解决办法是什么?
谢谢,格特
import numpy as np
import matplotlib.pyplot as plt
r= 500
s= 1000
y,x = np.ogrid[-s:s+1, -s:s+1]
mask = x*x + y*y <= r*r
aperture = np.ones((2*s+1, 2*s+1))
aperture[mask] = 0
plt.imshow(aperture)
plt.show()
ffta= np.fft.fft2(aperture)
plt.imshow(np.log(np.abs(np.fft.fftshift(ffta))**2))
plt.show()
发布于 2015-06-12 03:23:20
不幸的是,FFT的速度和精度很大程度上来自与输入相同大小的输出。
传统的增加输出傅里叶域表观分辨率的方法是通过零填充输入:np.fft.fft2(aperture, [4 * (2*s+1), 4 * (2*s+1)])
告诉快速傅立叶变换将你的输入压成高宽的4 * (2*s+1)
像素,即使输入变大四倍(16倍于像素数)。
从开始,我说“明显的”分辨率是因为实际的数据量没有增加,但是傅里叶变换看起来更平滑,因为输入域中的零填充会导致傅里叶变换插值输出。在上面的例子中,任何可以用一个像素看到的特性都会用四个像素显示。为了使这个完全具体化,这个例子显示零填充FFT的每四个像素在数字上与原始的未填充FFT的每个像素相同:
# Generate your `ffta` as above, then
N = 2 * s + 1
Up = 4
fftup = np.fft.fft2(aperture, [Up * N, Up * N])
relerr = lambda dirt, gold: np.abs((dirt - gold) / gold)
print(np.max(relerr(fftup[::Up, ::Up] , ffta))) # ~6e-12.
( relerr
只是一个简单的相对错误,您希望在2e-16
附近接近机器精度。零填充快速傅立叶变换的每4个样本与未加填充的快速傅立叶变换的最大误差是6e-12
,它非常接近机器精度,这意味着这两个阵列在数字上几乎等价。)末端除了。
零填充是解决问题最直接的方法。但这确实让你失去了很多记忆。这是令人沮丧的,因为你可能只关心一个很小的部分的转变。有一种叫做chirp变换(CZT,或俗称“变焦FFT")的算法可以做到这一点。如果您的输入是N
(对于您来说是2*s+1
),并且您只想要在任何地方计算FFT输出的M
样本,那么它将计算三个N + M - 1
大小的傅里叶变换,以获得输出的所需的M
样本。这也可以解决您的问题,因为您可以在感兴趣的区域请求M
示例,而且它不需要太多内存,尽管它至少需要3倍的CPU时间。缺点是CZT的可靠实现还没有出现在Numpy/Scipy中:请参阅它引用的枕木问题和代码。如果这是一种选择的话,Matlab的CZT似乎是可靠的;八度锻造也有这样的选择,而八度的人通常会努力去匹配/超过Matlab。
但是,如果你有内存,零填充输入是可行的。
https://stackoverflow.com/questions/30791905
复制相似问题