如何将 FFT 居中在四个中心像素的角上?

How to center FFT on the coner of the four center pixels?

我正在计算简单二维形状(例如圆形)的傅立叶变换。我对我不理解的 FFT 行为感到困惑:无论我的形状以一个像素为中心还是以四个像素的角为中心,生成的 FFT 都以一个像素为中心。这里有一些代码来解释:

import numpy as np
import matplotlib.pyplot as plt

nPix = 1000
pixelCentered = False

X,Y = np.indices((nPix,nPix),dtype=float)
if pixelCentered:
    X -= (nPix)/2 #this is centering my grid on one pixel
    Y -= (nPix)/2 #this is centering my grid on one pixel
else:
    X -= (nPix -1)/2 #this is centering my grid on the corner of four pixels
    Y -= (nPix -1)/2 #this is centering my grid on the corner of four pixels

x = X/(nPix/2)
y = Y/(nPix/2)
R = np.sqrt(x**2+y**2)
I = (R<0.5).astype(float)
PSF = np.fft.fftshift(np.fft.fft2(I))

plt.figure(1)
plt.clf()
plt.imshow(I)

plt.figure(2)
plt.clf()
plt.imshow(np.abs(PSF))

由于我的网格是均匀的,因此网格的准确中心位于四个中心像素的角上。但是,我根据坐标系 X, Y 创建形状,然后我可以控制形状中心的位置。如果我将 pixelCentered 设置为 True,则网格的确切中心位于像素 (nPix/2、nPix/2) 上。在这种情况下,我希望我的最大像素为像素 (nPix/2,nPix/2)。现在,如果我将 pixelCentered 设置为 False,则我的数组的确切中心不在一个像素内,而是在四个中心像素的角上。在这种情况下,我希望在 FFT 中四个中心像素具有最大值。但这不是我观察到的。事实上,不管我在圆上施加的位移如何,我的圆的 FFT 最大值始终以像素为中心 (nPix/2,nPix/2).

我在这里错过了什么?为什么最大强度不随形状移动? 干杯,

感谢 Homer512 的评论,我可以放心地回答我自己的问题。基本上,诀窍是在 pi/2 的空间域中添加相位。这仅在您在不更改坐标系的情况下使用零填充时才有效。 这里有一些示例代码供您使用:

import numpy as np
import matplotlib.pyplot as plt
nPix = 1000

X,Y = np.indices((nPix,nPix),dtype=float)
X -= (nPix)/2 #this is centering my grid on one pixel
Y -= (nPix)/2 #this is centering my grid on one pixel

x = X/(nPix/2)
y = Y/(nPix/2)
R = np.sqrt(x**2+y**2)

oversampling = 5
I = (R<(1/oversampling)).astype(float)
phase = -(np.pi/2*x)-(np.pi/2*y) #phase you add to center the image
complexPhase = I * np.exp(1j*phase)

plt.figure(1)
plt.clf()
plt.imshow(I)
PSF = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(complexPhase)))

plt.figure(2)
plt.clf()
plt.imshow(np.real(PSF*np.conj(PSF)))
plt.ylim([496,504])
plt.xlim([496,504])

现在,如果您希望重新缩放 x 和 y 以正确调整形状大小,并且仍然使 FFT 以网格的几何中心为中心,那么您应该这样做:

import numpy as np
import matplotlib.pyplot as plt

nPix = 1000

X,Y = np.indices((nPix,nPix),dtype=float)
X -= (nPix)/2 #this is centering my grid on one pixel
Y -= (nPix)/2 #this is centering my grid on one pixel

oversampling = 2

x = X/(nPix/2)*oversampling
y = Y/(nPix/2)*oversampling
R = np.sqrt(x**2+y**2)

I = (R<1).astype(float)
#Now your additional phase should scale with the oversampling
phase = -(np.pi/oversampling/2*x)-(np.pi/oversampling/2*y)
complexPhase = I * np.exp(1j*phase)

plt.figure(1)
plt.clf()
plt.imshow(I)
PSF = np.fft.fftshift(np.fft.fft2(np.fft.fftshift(complexPhase)))
plt.figure(2)
plt.clf()
plt.imshow(np.real(PSF*np.conj(PSF)))
plt.ylim([496,504])
plt.xlim([496,504])

我希望这是清楚的。

配镜师特别注意:这非常烦人,因为如果您进行波前传感并在重建中使用 FFT,这意味着由于您试图使 PSF 居中,您将始终获得偏移 tip/tilt 相位在数组中。这不是FFT的自然状态。