如何獲取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啊
這個問題問得很不清楚,按我的理解可能是這樣的:
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的分析頻率為
更詳細的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正弦波做傅立葉變換,得到
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;
這個採樣率就是你輸入的數據里,相鄰兩個點之間的間隔的倒數。比如說在你採集的數據里
那麼採樣率就是至於為什麼要這樣做,這是因為在連續傅立葉變換轉換到離散傅里葉變換的過程中,頻率間隔是這樣的首先我們得知道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/3935067http://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 |