在python中进行2D FFT时,我有一个关于规范化的简单问题。 我的理解是归一化因子可以通过使数组填充1来确定。
例如在1d中,[1,1,1,1]的FFT会给我[4 + 0j,0 + 0j,0 + 0j,0 + 0j]所以归一化因子应该是1 / N = 1 / 4。
在2D中,[[1,1],[1,1]]的FFT会给我[[4 + 0j,0 + 0j],[0 + 0j,0 + 0j]]所以归一化应该是1 / MN = 1 /(2 * 2)= 1/4
现在假设我们有一个3000乘3000矩阵,每个元素都有一个高斯分布值,均值为0.当我们FFT并归一化它(归一化因子= 1 /(3000 * 3000))时,我们得到一个平均幂的阶数10 ^ -7。
现在我们使用1000乘1000元素子区域(归一化因子= 1 /(1000 * 1000))重复此操作。我们从中获得的平均功率为10 ^ -6。我想知道为什么存在~10差异的因素。平均功率不应该相同吗?我错过了额外的归一化因子吗?
如果我们说因子差异是9,那么我可以猜测这来自元素的数量(3000 x 3000的元素数量是1000 x 1000的9倍),但这个额外的直观原因是什么因子?另外,我们如何确定绝对归一化因子以获得“真实的”潜在平均功率?
任何见解都将受到高度赞赏。提前谢谢!
示例代码:
import numpy as np
a = np.random.randn(3000,3000)
af = np.fft.fft2(a)/3000.0/3000.0
aP = np.mean(np.abs(af)**2)
b = a[1000:2000,1000:2000]
bf = np.fft.fft2(b)/1000.0/1000.0
bP = np.mean(np.abs(bf)**2)
print aP,bP
>1.11094908545e-07 1.00226264535e-06
答案 0 :(得分:3)
首先,重要的是要注意这个问题与1D和2D FFT之间的差异无关,而是与总阵容和平均功率如何与阵列中的元素数量进行比较。
当你说因子9来自a
中的9倍以上而不是b
时,你是完全正确的。也许令人困惑的是,你注意到你已经通过除以np.fft.fft2(a)/3000./3000.
和np.fft.fft2(b)/1000./1000.
进行了标准化。实际上,这些标准化对于使总(非平均)幂相等是必要的。空间和频率域。要获得平均值,您必须再次按数组大小划分。
您的问题实际上是关于Parseval定理,该定理指出两个域中的总功率(空间/时间和频率)是相等的。它对DFT的陈述是this。请注意,尽管右侧为1 / N,但这不是平均功率,而是总功率。 1 / N的原因是DFT的归一化约定。
放入Python,这意味着对于时间/空间信号sig
,Parseval等价可以表示为:
np.sum(np.abs(sig)**2) == np.sum(np.abs(np.fft.fft(sig))**2)/sig.size
下面是一个完整的例子,从一些玩具箱(一个和二维阵列填充一个1s)开始,以你自己的情况结束。请注意,我使用了numpy.ndarray的.size
属性,该属性返回数组中元素的总数。这相当于你的/1000./1000.
等希望这会有所帮助!
import numpy as np
print 'simple examples:'
# 1-d, 4 elements:
ones_1d = np.array([1.,1.,1.,1.])
ones_1d_f = np.fft.fft(ones_1d)
# compute total power in space and frequency domains:
space_power_1d = np.sum(np.abs(ones_1d)**2)
freq_power_1d = np.sum(np.abs(ones_1d_f)**2)/ones_1d.size
print 'space_power_1d = %f'%space_power_1d
print 'freq_power_1d = %f'%freq_power_1d
# 2-d, 4 elements:
ones_2d = np.array([[1.,1.],[1.,1.]])
ones_2d_f = np.fft.fft2(ones_2d)
# compute and print total power in space and frequency domains:
space_power_2d = np.sum(np.abs(ones_2d)**2)
freq_power_2d = np.sum(np.abs(ones_2d_f)**2)/ones_2d.size
print 'space_power_2d = %f'%space_power_2d
print 'freq_power_2d = %f'%freq_power_2d
# 2-d, 9 elements:
ones_2d_big = np.array([[1.,1.,1.],[1.,1.,1.],[1.,1.,1.]])
ones_2d_big_f = np.fft.fft2(ones_2d_big)
# compute and print total power in space and frequency domains:
space_power_2d_big = np.sum(np.abs(ones_2d_big)**2)
freq_power_2d_big = np.sum(np.abs(ones_2d_big_f)**2)/ones_2d_big.size
print 'space_power_2d_big = %f'%space_power_2d_big
print 'freq_power_2d_big = %f'%freq_power_2d_big
print
# asker's example array a and fft af:
print 'askers examples:'
a = np.random.randn(3000,3000)
af = np.fft.fft2(a)
# compute the space and frequency total powers:
space_power_a = np.sum(np.abs(a)**2)
freq_power_a = np.sum(np.abs(af)**2)/af.size
# mean power is the total power divided by the array size:
freq_power_a_mean = freq_power_a/af.size
print 'space_power_a = %f'%space_power_a
print 'freq_power_a = %f'%freq_power_a
print 'freq_power_a_mean = %f'%freq_power_a_mean
print
# the central 1000x1000 section of the 3000x3000 original array:
b = a[1000:2000,1000:2000]
bf = np.fft.fft2(b)
# we expect the total power in the space and frequency domains
# to be about 1/9 of the total power in the space frequency domains
# for matrix a:
space_power_b = np.sum(np.abs(b)**2)
freq_power_b = np.sum(np.abs(bf)**2)/bf.size
# we expect the mean power to be the same as the mean power from
# matrix a:
freq_power_b_mean = freq_power_b/bf.size
print 'space_power_b = %f'%space_power_b
print 'freq_power_b = %f'%freq_power_b
print 'freq_power_b_mean = %f'%freq_power_b_mean