2013-10-18 63 views
2

我有一個簡單的問題,關於在python中做二維FFT時的規範化。 我的理解是規範化因素可以通過使數組填充1來確定。例如在1d中,[1,1,1,1]的FFT會給我[4 + 0j,0 + 0j,0 + 0j,0 + 0j],所以歸一化因子應該是1/N = 1/4。二維FFT的歸一化

在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

我認爲FFT也是一個平均過程,所以你需要根據量化進行補償。 20.log(3,10)= 9.54:你的因素也許在這裏。更多信息:http://www.lumerink.com/courses/ece697/docs/Papers/The%20Fundamentals%20of%20FFT-Based%20Signal%20Analysis%20and%20Measurements.pdf – lucasg

回答

2

首先,要注意,這個問題是不相關的一維和二維快速傅里葉變換之間的區別是很重要的,而是權力如何全面和平均功率規模與元素的數量在一個數組中。

當你說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,帕斯瓦爾等價可以表述爲:

np.sum(np.abs(sig)**2) == np.sum(np.abs(np.fft.fft(sig))**2)/sig.size

下面是一個完整的例子,從一些玩具例(一和二二維數組填充一個1),並以您自己的情況結束。請注意,我使用了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