如何规范化 numpy(实数)傅里叶变换的频谱,以便应用 parseval 定理?
How to normalize the spectrum of a numpy (real) fourier transform so that parcevals theorem applies?
目前,我正在考虑拍摄图像及其光谱。现在 Parceval 的定理说两者应该具有相等的能量。但是,当我尝试在某些图像上对此进行测试时,numpy 真实 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,否则它们仍然不相等):
import numpy as np
from PIL import Image
im = np.array(Image.open('/images/building.jpeg')).astype('float64')
spectral_im = np.fft.fft2(im, axes = (0,1), norm = 'ortho')
def getNorm(im):
return np.sum(np.abs(im) ** 2)
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)))
Parceval 定理指出信号的 平方 上的积分与傅里叶变换相同。所以getNorm
函数应该定义为
def getNorm(im):
return np.sum(np.abs(im)**2)
然后是FFT归一化问题。您需要通过图像区域(尺寸的乘积)对 FFT 进行归一化:
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
最后,不要用rfft
来验证Parceval定理。 rfft
的问题在于它知道频谱是对称的,因此它会跳过负半部分。但是,积分(总和)中缺少这一半。这听起来好像应该偏离 2 倍,但事实并非如此,因为 DC(均值)分量被 rfft
完全保留(可以找到更多详细信息 ) .最好使用普通的 FFT (fft2
),省去一些麻烦。
与 Parceval 定理中使用的形式相比,标准前向 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
目前,我正在考虑拍摄图像及其光谱。现在 Parceval 的定理说两者应该具有相等的能量。但是,当我尝试在某些图像上对此进行测试时,numpy 真实 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,否则它们仍然不相等):
import numpy as np
from PIL import Image
im = np.array(Image.open('/images/building.jpeg')).astype('float64')
spectral_im = np.fft.fft2(im, axes = (0,1), norm = 'ortho')
def getNorm(im):
return np.sum(np.abs(im) ** 2)
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)))
Parceval 定理指出信号的 平方 上的积分与傅里叶变换相同。所以getNorm
函数应该定义为
def getNorm(im):
return np.sum(np.abs(im)**2)
然后是FFT归一化问题。您需要通过图像区域(尺寸的乘积)对 FFT 进行归一化:
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
最后,不要用rfft
来验证Parceval定理。 rfft
的问题在于它知道频谱是对称的,因此它会跳过负半部分。但是,积分(总和)中缺少这一半。这听起来好像应该偏离 2 倍,但事实并非如此,因为 DC(均值)分量被 rfft
完全保留(可以找到更多详细信息 fft2
),省去一些麻烦。
与 Parceval 定理中使用的形式相比,标准前向 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