Python 如何规范化numpy(实)傅里叶变换的频谱,从而应用parcevals定理?

Python 如何规范化numpy(实)傅里叶变换的频谱,从而应用parcevals定理?,python,numpy,fft,Python,Numpy,Fft,目前,我正在考虑拍摄一张图像及其光谱。现在,帕切瓦尔定理说,两者的能量应该相等。然而,当我尝试在一些图像上测试这一点时,numpy real FFT函数似乎并非如此 这是我用于测试的代码: import numpy as np from PIL import Image im = np.array(Image.open('/images/building.jpeg')) spectral_im = np.fft.rfft2(im, axes = (0,1), norm = 'ortho')

目前,我正在考虑拍摄一张图像及其光谱。现在,帕切瓦尔定理说,两者的能量应该相等。然而,当我尝试在一些图像上测试这一点时,numpy real FFT函数似乎并非如此

这是我用于测试的代码:

import numpy as np
from PIL import Image

im = np.array(Image.open('/images/building.jpeg'))
spectral_im = np.fft.rfft2(im, axes = (0,1), norm = 'ortho')

def getNorm(im):
    return np.sum(np.abs(im))

print('Norm of the image: %d' % getNorm(im))
print('Norm of the spectrum of the image: %f' % getNorm(spectral_im))
print('Difference between norms: %f' % (getNorm(im) - getNorm(spectral_im)))
我希望每个图像的标准差(大约)为0,但是我尝试过的每个图像的标准差都有一个数量级。有人能看出我做错了什么吗

在答案的帮助下,下面是正确的代码(注意对float64的额外转换,否则它们仍然不相等):


帕切瓦尔定理表明,信号的平方上的积分和傅里叶变换是相同的。因此,
getNorm
函数应定义为

def getNorm(im):
    return np.sum(np.abs(im)**2)
然后是FFT归一化问题。您需要通过图像区域(尺寸的乘积)对FFT进行规格化:


最后,不要使用
rfft
来验证帕切瓦尔定理。rfft的问题在于它知道光谱是对称的,所以跳过了负半部分。但是,积分(和)中缺少这一半。这使得它听起来像应该关闭2倍,但事实并非如此,因为DC(平均值)分量被
rfft
完全保留(更多详细信息可以找到)。最好使用普通的FFT(
fft2
)并省去一些麻烦。

与帕切瓦尔定理中使用的形式相比,标准的前向FFT中有一个额外的因子
sqrt(N)
。考虑到这一点,可以使事情按预期进行:

x = np.random.rand(200, 100)
f = np.fft.fft2(x)
np.allclose(np.sum(x ** 2),
            np.sum(abs(f) ** 2 / x.size))
# True
x = np.random.rand(321, 456)
f = np.fft.fft2(x) / np.sqrt(321 * 456)
print(np.sum(np.abs(x)**2))  # 48654.563992061871
print(np.sum(np.abs(f)**2))  # 48654.563992061878
x = np.random.rand(200, 100)
f = np.fft.fft2(x)
np.allclose(np.sum(x ** 2),
            np.sum(abs(f) ** 2 / x.size))
# True