如何獲取FFT序列中每個點的頻率值?

例如H是一個向量,經FFT變換後得到序列F,要怎麼得到F中每個點的頻率值呢?matlab中函數fft(H,n),n表示fft序列的長度,應該如何選取合適的n呢?謝謝各位啦!

****可能我的問題問得不太清楚,我再把問題補充完整一點吧:

我是基於遊程(run length)直方圖提取圖像特徵,先統計一幅圖的遊程直方圖,得到向量H(每個元素值在0~1範圍),再對H做FFT變換,得到fft序列F,特徵是高階矩,定義為:

L就是F序列的長度,F下標i先忽略吧,n是階數,!重點!是文中有句話是:Fi(fj) is the component of Fi at frequency fj,但是不知道怎麼求這個fft序列F中某個點的頻率值fj。

論文名:BLIND IMAGE STEGANALYSIS BASED ON RUN-LENGTH HISTOGRAM ANALYSIS

*****另外這篇論文中上述Mn公式引用了如下一篇文章中的定義:

!!不知道作者說的 「傅氏變換的 第k次頻率」 是什麼?!!

論文名:《基於直方圖頻域統計矩的圖像隱寫分析》


FFT結果任意一點的頻率為:假設信號採樣頻率為fs,從採樣定理可以知道,信號抽樣後,抽樣信號的頻譜是周期譜,其頻譜的周期是抽樣頻率fs,因此,對信號做FFT時,無論你取多少點,其分析的頻率範圍就是0~fs,所以,如果你做N點的FFT(其實是離散傅里葉變換),則,FFT結果的兩點之間的頻率間隔是fs/N,這樣,任一點k(k=0~N-1)代表的頻率就是k*fs/N。另外,這N個點的FFT值是以N/2為對稱的,所以,一般真正用到的只有N/2個點。N點取的大隻說明譜線密一些而已,注意:採樣定理非常重要啊!


這幾天我在幫師兄做傅里葉分析,就是從示波器踩過來的數據,保存在excel文件中。用matlab讀取,進行fft運算。大概通過幾天的學習dft,了解到如果你拿來一個向量,N個點。進行fft後結果當然也是N個點。但是這些點的頻率你是無法得知的。因為你沒有交代著N個點的時間長度。

以我最近幫師兄做的工作為例。示波器對300HZ電壓進行採樣,時長0.1s。那麼也就是30個周波。由於示波器的採樣頻率很高,所得到的數據是50w個點。這僅僅是0.1s啊

保存在exce結果通過matlab讀取後,進行fft運算。結果也是50w 個點。於是問題來了,哪一個點是我要的300hz呢。答案是第31個點。

為什麼呢,因為matlab數組是從1開始,第一個點是直流分量。即0hz,那為什麼第31點是300hz呢。因為時間長度是0.1s。那麼這段信號進行fft的解析度就是10hz。所以300hz就是 30+1的點。

順便說一句,matlab進行fft運算的結果,幅值要經過*2/n的運算才能得到真實值。n是採樣點個數。還有,直流分量要再除以2,即第一個點雖然是直流 但是 幅值是真實值的2倍。原理高數傅里葉級數講過,已經喂狗。

回答的不好,不對的地方請高手指正。


這個問題問得很不清楚,按我的理解可能是這樣的:

H是一個向量(通常意義下應該是一串等時間採樣的時間序列),設H的採樣率為fs,即採樣時間為dt = 1/fs,採樣點為N,則總時長T = N*dt。對N點序列做FFT得到的頻譜,其分布區間為[0, fs),而頻譜點的間隔即為df = 1/T。根據Nyquist採樣定理,其中只有[0,fs/2)有信息量,剩下一半是共軛對稱的。所以這段話有兩個重要的信息,採樣頻率fs決定了可分辨的頻率範圍是[0,fs/2),而採樣的總時長決定了頻域解析度df

舉個例子:在電力系統中計算諧波。中國電網頻率是50Hz,一個周波就是20ms,假設採樣是一周波256個點,即採樣率是fs = 256*50 = 12800Hz,dt = 1/12800,採樣點N = 256個(正好一個周期),則FFT的結果也是256個點,分別對應直流量,基波(50Hz),二次諧波(100Hz),三次諧波(150Hz),直到127次諧波;剩下的129個點是個特殊點,再剩下的127個點是跟1-127次共軛對稱的值。

如果我的理解是對的,題主想問的是要把FFT的結果n個點畫出來,其橫軸應該怎麼設置,那答案就是0:1/T : (n-1)/T,而縱軸一般是兩個分別畫:幅值和相角。

其實matlab自己fft這個函數的例子就有。


連續的時間域信號x(t)以採樣率fs進行採樣後,得到離散的時間域信號x(n)(即題主所指的向量H),然後經過N點DFT得到離散的頻率域序列X(m)(即題主所指的序列F)。

DFT輸出值X(m)對應的頻率取決於採樣率fs和樣點個數N。例如:如果採樣率為500Hz,然後進行16點DFT,那麼基頻為fs/N=500/16=31.25Hz,X(m)對應的頻率為基頻的整數倍,即

X(0)對應第1個頻率項,頻率=0 × 31.25=0Hz,

X(1)對應第2個頻率項,頻率=1 × 31.25=31.25Hz,

X(2)對應第3個頻率項,頻率=2 × 31.25=62.5Hz,

X(3)對應第4個頻率項,頻率=3 × 31.25=93.75Hz,

...

...

X(15)對應第16個頻率項,頻率=15 × 31.25=468.75Hz.

N點DFT的分析頻率為

f_{analysisx} (m)=frac{mf_s} {N}

更詳細的DFT計算過程見理解離散傅里葉變換


先來看看一段簡單的MATLAB代碼

dt = 0.002;
t = 0:dt:2;
f0 = 100;
x = sin(2*pi*f0*t);
X = fft(x,length(x));
plot(abs(X),"linewidth",2);
set(gcf,"color","white")
axis tight

很清楚,這是給一個100Hz正弦波做傅立葉變換,得到

很明顯得到一個單頻信號,不過下標沒有對準100Hz。不過沒關係。換成下面的代碼再跑一次:

dt = 0.002;
t = 0:dt:2;
f0 = 100;
N = length(x);
x = sin(2*pi*f0*t);
X = fft(x,N);

f = (0:N-1)/N * (1/dt);
plot(f,abs(X),"linewidth",2);
set(gcf,"color","white")
axis tight

看頻譜的時候,只要看前一半就好了。要得到真實頻率的下標其實很簡單。只要先將頻率歸一化

f = (0:N-1)/N;

然後,再乘以採樣率

f = f * fs;

這個採樣率就是你輸入的數據里,相鄰兩個點之間的間隔的倒數。比如說在你採集的數據里

Delta t=t(n+1)-t(n)

那麼採樣率就是

f_s=1/Delta t

至於為什麼要這樣做,這是因為在連續傅立葉變換轉換到離散傅里葉變換的過程中,頻率間隔是這樣的

dw
ightarrow Delta w=2pi /(NDelta t)


首先我們得知道H的採樣間隔和採樣的時長即採樣的點數。

比如當採樣間隔為ts=0.01,採樣時長為t=10即1001個點。

設fs=1/ts的話,那麼頻譜的解析度等於fs除以採樣的點數即df=fs/1001

在Matlab里fft後經過fftshift後頻譜的範圍為f=-fs/2:df:fs/2

然後就可以獲得每個點的頻率了。

n的話看你怎麼用,不填寫n的話它為H的長度但是n超過H長度的話Matlab默認H序列補0到n這麼長。

上面的涉及到的知識點要看信號處理的書。


短時傅立葉變換


看過的最好的講解傅立葉變換的文章

http://daily.zhihu.com:80/story/3935067

http://daily.zhihu.com:80/story/3939307

關於如何選取合適的n,可以參考胡廣書《數字信號處理(第二版)》3.7節


為何 看頻譜的時候,只要看前一半就好了 ?


你只需要知道這個序列的採樣頻率Fs,然後:

plot(linspace(-Fs/2,Fs/2,length(H)),abs(fftshift(fft(H))));

就OK了。


Fast Fourier transform

我覺得這個已經解釋的很好了。

至於為什麼要使用nextpow2,是fft蝶形演算法要求點數是2的整數次冪。當然你寫輸入點數比如1000而不是1024也是可以的,只不過計算時候會自動把1001-1024點的值都補成0。理論上說n取得越大頻率解析度越高,但是時間解析度會下降(比如你想把頻率解析度變成原來兩倍,除非你願意後面那些點都是0——有個高大上的方法稱之為補零法。現在終於曉得是怎麼來的了。要麼就同樣的精度原來采了一秒鐘就能拿去轉換,現在要等兩秒鐘。所以魚和熊掌不可兼得)。不過太高也是沒有必要的,你可以自己改改參數感受下。

別的應該沒什麼了吧。


推薦閱讀:

為什麼在信號處理中一個域的離散會造成另一個域的周期延拓?
正弦函數究竟有多神奇?為什麼?
二維傅里葉變換是怎麼進行的?

TAG:圖像處理 | MATLAB | 傅里葉變換FourierTransform | fft |