如何将 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的自然状态。
我正在计算简单二维形状(例如圆形)的傅立叶变换。我对我不理解的 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的自然状态。