解析MATLAB短时傅里叶变换函数spectrogram()

如何理解spectrogram()函数的输入输出参数?

Abstract: 我想这篇博文可以帮你弄清楚这几个问题,输出图像表示什么意思,spectrogram()函数有无返回值调用时图像如何转换,函数输入输出参数的的含义及其对谱图分辨力的影响。

Note: spectrogram()函数的句法和参数大概含义(物理意义和取值范围)可参考MATLAB help center和网友中文转述。函数的底层代码可以在MATLAB命令行窗口输入open/eidt spectrogram 查看。

调用方式一

[S,F,T,P]=spectrogram(x,window,noverlap,nfft,fs) %有返回值
spectrogram(x,window,noverlap,nfft,fs,'yaxis')	 %无返回值调用,直接输出频谱图

需要注意的是,上述调用方式中,若输入参数为缺省值,则会以默认参数(见Note中推荐文档)进行计算。以MATLAB自带的非平稳信号quadratic chirp为例,对其进行时频分析,测试代码如下:

Nw = 128; 							%窗函数长度
window = hamming(128);  			% 使用海明窗(默认窗函数)
noverlap = 120; 					%重叠长度
nfft = 2^nextpow2(length(window)); 	%DFT点数
fs = 1000; 							%采样率
t=0:1/fs:2;                                          % 2 secs @ 1kHz sample rate
y=chirp(t,100,1,200,'q');                   		 % Start @ 100Hz, cross 200Hz at t=1sec 
spectrogram(y, window, noverlap, nfft,fs, 'yaxis');  % Display the spectrogram
h=colorbar;
h.Label.String = 'Power/Frequency(dB/Hz)'
title('Quadratic Chirp: start at 100Hz and cross 200Hz at t=1sec');

1. 如何分析这个图?

  • 颜色:首先最重要的一点是,该图像不同颜色区域表示的是对应频率下信号功率谱密度的分贝值,即单位为Power/Frequency(dB/Hz);

  • 时间轴: 其次,时间轴表示的是信号时长,其长度n为 N x − l e n g t h ( w i n d o w ) l e n g t h ( w i n d o w ) − n o v e r l a p + 1 = N x − n o v e r l a p l e n g t h ( w i n d o w ) − n o v e r l a p = n \frac{Nx - length(window)}{length(window) - noverlap} + 1 = \frac{Nx - noverlap}{length(window)-noverlap} = n length(window)noverlapNxlength(window)+1=length(window)noverlapNxnoverlap=n
    该数值表示在这信号时长内进行了多少次快速傅里叶变换,该数值由窗函数的宽度和重叠区域长度共同决定;

  • 频率轴:频率轴以模拟频率表示,其显示范围为采样频率的一半。 为什么呢?由傅里叶变换和采样定理知识我们可以知道,信号经过傅里叶变换后频谱对称,实际信号频率范围其实只有采样频率一半。由于频率轴只显示采样频率一半,故其长度为nfft/2+1或(nfft+1)/2,分别对应nfft为even和odd。频率轴的分辨率受nfft的影响,为1/nfft*fs。

2. DFT点数nfft的选择

这个值的选择与快速傅里叶变换中一致,通常取最接近信号长度的2的整数次幂,即 nfft = 2^nextpow2(length(window)) ,这里的信号长度即窗函数长度,因为是对每个加窗信号的快速傅里叶变换。缺省值为 m a x ( 256 , 2 p ) , p = ⌈ l o g 2 N w ⌉ max(256,2^p), p = ⌈log_2 ^{Nw}⌉ max(256,2p),p=log2Nw

3. noverlap对输出结果的影响

noverlap表示窗函数在移动过程中与前一个窗口位置的重叠区域大小,从前面对时间轴的分析公式可以看到,该参数会影响时间轴的分辨率。当该参数为0时,信号被窗函数进行无间隔无重叠分配,可以想象执行该过程时,时间轴上每一个数据长度(Nw)对应一个持续的fft显示,图像上表现为时间轴上出现明显的“拉伸”。而随着noverlap参数的引入,增大了时间轴分辨率,即每隔(Nw - noverlap)长度进行一次频率轴的更新,随着noverlap逐渐接近Nw,图像上表现为时间轴更加“细腻”,但随之而来的肯定是计算次数的增加。

3. 窗口长度Nw对输出结果的影响

窗口长度对短时傅里叶变换的影响不言而喻,窗口大则频域分辨率越高,相应的时间上分辨率下降。该值的正确选择是短时傅里叶算法的一个难题,故引出了小波变换等方法。

如何由带返回值的调用形式得到一致的频谱图呢?

[S,F,T,P]=spectrogram(x,window,noverlap,nfft,fs)
首先对该函数的输出参数进行准确的认识,下面是该函数底层代码给出的解释

%   Each column of S contains an estimate of the short-term, time-localized
%   frequency content of the signal X.  Time increases across the columns
%   of S, from left to right.  Frequency increases down the rows, starting
%   at 0.  If X is a length NX complex signal, S is a complex matrix with
%   NFFT rows and k = fix((NX-NOVERLAP)/(length(WINDOW)-NOVERLAP)) columns.
%   For real X, S has (NFFT/2+1) rows if NFFT is even, and (NFFT+1)/2 rows
%   if NFFT is odd.  
%   
%   [S,F,T] = SPECTROGRAM(...) returns a vector of frequencies F and a
%   vector of times T at which the spectrogram is computed. F has length
%   equal to the number of rows of S. T has length k (defined above) and
%   its value corresponds to the center of each segment.

1. 参数S和P的关系

S为信号x进行n次快速傅里叶变换后的结果,为一复数矩阵,横向按时间递增,纵向按频率递增。包含nfft/2+1或(nfft+1)/2行、n列,推导见前述。P为信号的功率谱密度,为一实矩阵,维数与S保持一致。
由信号分析的知识可以知道,功率谱密度可以由信号的快速傅里叶变换结果的绝对值平方除以信号长度表示,但是在这里,为了弥补窗函数的影响,还需要添加一个变换系数k。即 P ( i , j ) = k ∣ S ( i , j ) ∣ 2 , k = { 2 f s ∑ n = 1 L ∣ w ( n ) ∣ 2 , 单 边 P S D 1 f s ∑ n = 1 L ∣ w ( n ) ∣ 2 , 双 边 P S D P(i,j) = k|S(i,j)|^2, k = \begin{cases} \frac{2}{fs\sum_{n=1}^{L}|w(n)|^2}, &单边PSD\\ \frac{1}{fs\sum_{n=1}^{L}|w(n)|^2},&双边PSD\end{cases} P(i,j)=kS(i,j)2,k={fsn=1Lw(n)22,fsn=1Lw(n)21PSDPSD
当函数spectrogram()直接调用时输出的是以分贝值表示的PSD,由上面的讨论,我们可以利用S或者P得到一致的谱图

clear 
Nw = 128;
window = hamming(128);
noverlap = 120;
nfft = 2^nextpow2(length(window));
fs = 1000;
t=0:1/fs:2;                                         % 2 secs @ 1kHz sample rate
y=chirp(t,100,1,200,'q');                   % Start @ 100Hz, cross 200Hz at t=1sec 

subplot(131)
spectrogram(y, window, noverlap, nfft,fs, 'yaxis');  % Display the spectrogram
title('Call directly')
h=colorbar;
h.Label.String = 'Power/Frequency(dB/Hz)'

[S, F, T, P] = spectrogram(y, window, noverlap, nfft,fs);
subplot(132)
imagesc(T,F,10*log10(P));
title('Draw with P')
h=colorbar;
h.Label.String = 'Power/Frequency(dB/Hz)'

subplot(133)
k = 2/(fs*(window'*window))
imagesc(T,F,10*log10(abs(S).*abs(S)*k));
title('Draw with S')
h=colorbar;
h.Label.String = 'Power/Frequency(dB/Hz)'

解析MATLAB短时傅里叶变换函数spectrogram()_第1张图片

2. 关于参数T的认识

我们已经知道输出的图像时间轴分辨率受制于窗口大小Nw和重叠长度noverlap,其长度为k。T中的数值为每个segment的中间值,什么意思呢?这里的segment理解为加的窗口,以本文中的程序为例,我使用的是采样频率为1000Hz的2s chirp信号,窗口长度Nw为128,noverlap为120。那么T的第一个数据该是多少?即1/1000 * 128/2 = 0.064s,而后每次递增1/1000 *(Nw - noverlap)= 0.008s。
了解了T的含义后,我们便可以根据结果(S、P)分别得到各个时间segment的频谱,例如我想查看信号1秒附近(±Nw/1000/2 s)的功率谱,只需要输入plot(P(:, find(T==1)))。

调用方式二

f = 100:0.05:300;
[S, F, T, P] = spectrogram(y, window, noverlap, f,fs);
spectrogram(y, window, noverlap, f,fs, 'yaxis');

%   [S,F,T] = SPECTROGRAM(X,WINDOW,NOVERLAP,F,Fs) where F is a vector of 
%   frequencies in Hz (with 2 or more elements) computes the spectrogram at 
%   those frequencies using the Goertzel algorithm. The specified 
%   frequencies in F are rounded to the nearest DFT bin commensurate with 
%   the signal's resolution. 

该调用方式下,nfft由具体的频率范围取代,频率轴显示范围由f上下限决定,频率分辨率由其间隔决定。

你可能感兴趣的:(信号处理【EEG,etc.】)