数字信号功率谱估计相关方法的MATLAB实现

    在参阅了其他博客关于功率谱估计Matlab程序实现方法,进行重新整理、运行调试程序以及知识点总结,最终可直接运行!主要包括pmem(最大熵法)、psd(Welch法)、pmtm(多窗口法)、pmusic(多信号分类法)、分段平均周期图法(Bartlett)、

加窗平均周期图法等的介绍,具体使用哪种方法可以根据自己程序实现结果进行选择。


1. 基本方法

      功率谱方法可以分为两种,直接法和间接法。直接法也称为周期图法,它是直接对有限个样本数据进行傅里叶变换来得到功率谱。样本数据越长,直接法获得的分辨率越高。间接法则是先对有限个样本数据进行自相关估计,再进行傅里叶变换,最后得到功率谱。

求取功率谱密度估计的方法。假定有限长随机信号序列为x(n)。它的Fourier变换和功率谱密度估计存在下面的关系:

                                                                     

信号功率谱 python 信号功率谱matlab_采样频率

式中,N为随机信号序列x(n)的长度。在离散的频率点f=kΔf,有:

                                           

信号功率谱 python 信号功率谱matlab_数据_02

 

其中,FFT[x(n)]为对序列x(n)的Fourier变换,由于FFT[x(n)]的周期为N,求得的功率谱估计以N为周期。

clear;  
fs=1000; %采样频率  
nfft=1024; %采样的点数
n=0:1/fs:1; 
xn=cos(2*pi*40*n)+3*cos(2*pi*100*n)+randn(size(n)); %产生含有噪声的序列 
window=boxcar(length(xn)); %使用矩形窗(默认为矩形窗,窗的大小与信号长度一样)  
[Pxx,f]=periodogram(xn,window,nfft,Fs); %直接法  
plot(f,10*log10(Pxx));  %绘制分贝形式的功率谱

用有限长样本序列的Fourier变换来表示随机序列的功率谱,只是一种估计或近似,不可避免存在误差。为了减少误差,使功率谱估计更加平滑,可采用分段平均周期图法(Bartlett法)、加窗平均周期图法(Welch法)等方法加以改进。

2. 改进方法----分段平均周期图法(Bartlett法)

       将信号序列x(n),n=0,1,…,N-1,分成互不重叠的P个小段,每小段由m个采样值,则P*m=N。对每个小段信号序列进行功率谱估计,然后再取平均作为整个序列x(n)的功率谱估计。

%% 分段平均周期图法(Bartlett),不重叠分段功率谱估计

fs=128;sigLength=1152;                        %采样频率、数据长度
Nsec=256;n=0:sigLength-1;t=n/fs;              %分段数据点数,分段间隔,时间序列
pxx1=abs(fft(x_sigal(1:256),Nsec).^2)/Nsec;   %第一段功率谱
pxx2=abs(fft(x_sigal(257:512),Nsec).^2)/Nsec; %第二段功率谱
pxx3=abs(fft(x_sigal(515:768),Nsec).^2)/Nsec; %第三段功率谱
pxx4=abs(fft(x_sigal(769:1024),Nsec).^2)/Nsec; %第四段功率谱
Pxx=10*log10((pxx1+pxx2+pxx3+pxx4)/4);         %平均得到整个序列功率谱
f=(0:length(Pxx)-1)*fs/length(Pxx);            %给出功率谱对应的频率
figure;
plot(f(1:Nsec/2),Pxx(1:Nsec/2));               %绘制功率谱曲线
xlabel('频率/Hz');ylabel('功率谱 /dB');
title('平均周期图(无重叠) N=4*256');
grid on

        平均周期图法还可以对信号x(n)进行重叠分段,如按2:1重叠分段,即前一段信号和后一段信号有一半是重叠的。对每一小段信号序列进行功率谱估计,然后再取平均值作为整个序列x(n)的功率谱估计。这两种方法都称为平均周期图法,一般后者比前者好。

fs=128;sigLength=1152;                    %采样频率、数据长度
Nsec=256;n=0:sigLength-1;t=n/fs;          %分段数据点数,分段间隔,时间序列
pxx1=abs(fft(x_sigal(1:256),Nsec).^2)/Nsec;    %第一段功率谱
pxx2=abs(fft(x_sigal(129:384),Nsec).^2)/Nsec;  %第二段功率谱
pxx3=abs(fft(x_sigal(257:512),Nsec).^2)/Nsec;  %第三段功率谱
pxx4=abs(fft(x_sigal(385:640),Nsec).^2)/Nsec;  %第四段功率谱
pxx5=abs(fft(x_sigal(513:768),Nsec).^2)/Nsec;  %第五段功率谱
pxx6=abs(fft(x_sigal(641:896),Nsec).^2)/Nsec;  %第六段功率谱
pxx7=abs(fft(x_sigal(769:1024),Nsec).^2)/Nsec; %第七段功率谱
Pxx=10*log10((pxx1+pxx2+pxx3+pxx4)/4);         %平均得到整个序列功率谱
f=(0:length(Pxx)-1)*fs/length(Pxx);            %给出功率谱对应的频率
figure;	
plot(f(1:Nsec/2),Pxx(1:Nsec/2));               %绘制功率谱曲线
xlabel('频率/Hz');ylabel('功率谱 /dB');
title('平均周期图(重叠一半) N=4*256');
grid on

3. 改进方法----加窗平均周期图法

加窗平均周期图法是对分段平均周期图法的改进。在信号序列x(n)分段后,用非矩形窗口对每一小段信号序列进行预处理,再采用前述分段平均周期图法进行整个信号序列x(n)的功率谱估计。由窗函数的基本知识可知,采用合适的非矩形窗口对信号进行处理可减小“频谱泄露”,同时可增加频峰的宽度,从而提高频谱分辨率。

%% 加窗平均周期图法,不重叠分段加窗方法功率谱估计

fs=128;sigLength=1152;                         %采样频率、数据长度
w=hanning(256);                                %采用的窗口数据
Nsec=256;n=0:sigLength-1;t=n/fs;               %分段数据点数,分段间隔,时间序列
pxx1=abs(fft(w.*x_sigal(1:256),Nsec).^2)/norm(w)^2;   %第一段加窗振幅谱平方
pxx2=abs(fft(w.*x_sigal(257:512),Nsec).^2)/norm(w)^2; %第二段加窗振幅谱平方
pxx3=abs(fft(w.*x_sigal(513:768),Nsec).^2)/norm(w)^2; %第三段加窗振幅谱平方
pxx4=abs(fft(w.*x_sigal(769:1024),Nsec).^2)/norm(w)^2; %第四段加窗振幅谱平方
Pxx=10*log10((pxx1+pxx2+pxx3+pxx4)/4);                 %求得平均功率谱,转换为dB
f=(0:length(Pxx)-1)*fs/length(Pxx);                    %求得频率序列
figure;
plot(f(1:Nsec/2),Pxx(1:Nsec/2));                       %绘制功率谱曲线
xlabel('频率/Hz');ylabel('功率谱/dB');
title('加窗平均周期图(无重叠) N=4*256');
grid on

     加窗平均周期图法还可以对信号x(n)进行重叠分段,如按2:1重叠分段,即前一段信号和后一段信号有一半是重叠的。

%% 加窗平均周期图法,重叠一半分段加窗功率谱估计
fs=128;sigLength=1152;                         %采样频率、数据长度
w=hanning(256);                                %采用的窗口数据
Nsec=256;n=0:sigLength-1;t=n/fs;               %分段数据点数,分段间隔,时间序列
pxx1=abs(fft(w.*x_sigal(1:256),Nsec).^2)/norm(w)^2;   %第一段加窗振幅谱平方
pxx2=abs(fft(w.*x_sigal(129:384),Nsec).^2)/norm(w)^2; %第二段加窗振幅谱平方
pxx3=abs(fft(w.*x_sigal(257:512),Nsec).^2)/norm(w)^2; %第三段加窗振幅谱平方
pxx4=abs(fft(w.*x_sigal(385:640),Nsec).^2)/norm(w)^2; %第四段加窗振幅谱平方
pxx5=abs(fft(w.*x_sigal(513:768),Nsec).^2)/norm(w)^2; %第五段加窗振幅谱平方
pxx6=abs(fft(w.*x_sigal(641:896),Nsec).^2)/norm(w)^2; %第六段加窗振幅谱平方
pxx7=abs(fft(w.*x_sigal(769:1024),Nsec).^2)/norm(w)^2; %第七段加窗振幅谱平方
Pxx=10*log10((pxx1+pxx2+pxx3+pxx4+pxx5+pxx6+pxx7)/7); %平均功率谱转换为dB
f=(0:length(Pxx)-1)*fs/length(Pxx);                   %求得频率序列
figure;
plot(f(1:Nsec/2),Pxx(1:Nsec/2));                      %绘制功率谱曲线
xlabel('频率/Hz');ylabel('功率谱/dB');
title('加窗平均周期图(重叠一半) N=4*256');
grid on

4. Welch法功率谱估计及其MATLAB函数  

自功率谱估计(PSD)和两个信号序列的互功率谱估计(CSD)。

MATLAB信号处理工具箱函数提供了专门的函数PSD和CSD自动实现Welch法估计,而不需要自己编程。

(1) 函数psd利用Welch法估计一个信号自功率谱密度,函数调用格式为:

[Pxx,f]=psd(x,Nfft,Fs,window,Noverlap,’dflag’)

式中,

x为信号序列;

Nfft为采用的FFT长度。这一值决定了功率谱估计速度,当Nfft采用2的幂时,程序采用快速算法;

Fs为采样频率;

Window定义窗函数和x分段序列的长度。窗函数长度必须小于或等于Nfft,否则会给出错误信息;

Noverlap为分段序列重叠的采样点数(长度),它应小于Nfft;

dflag为去除信号趋势分量的选择项:’linear’,去除线性趋势分量,’mean’去除均值分量,’none’不做去除趋势处理。

Pxx为信号x的自功率谱密度估计。

f为返回的频率向量,它和Pxx对应,并且有相同长度。

注意:

①在psd函数调用格式中,缺省值为:Nfft=min(256,length(x)),Fs=2Hz, window=hanning(Nfft),noverlap=0. 若x是实序列,函数psd仅计算频率为正的功率

②程序前半部分中频率向量f的创建方法。它与函数psd的输出Pxx长度的关系如下:若x为实序列,当Nfft为奇数时,f=(0:(Nfft+1)/2-1)/Nfft;当Nfft为偶数时,f=(0:Nfft/2)/Nfft。

函数还可以计算带有置信区间的功率谱估计,调用格式为:

[Pxx,Pxxc,f]=psd(x,Nfft,Fs,window,Noverlap,p)

式中,p为置信区间,0<=p<=1。

由此可知,滤波器输入白噪声序列的输出信号的功率谱或自相关可以确定滤波器的频率特性。

%% psd(Welch法)功率谱估计

fs=128;sigLength=1152;                %采样频率、数据点数
Nfft=1024;n=0:sigLength-1;t=n/128;    %傅里叶变换点数、时间序列
window=hanning(256);                  %选用的窗口大小	
noverlap=128;                         %分段序列重叠的采样点数(长度)
dflag='none';                         %不做趋势处理
[Pxx,Pxxc,f]=psd(x_sigal(:,1),Nfft,fs,window,noverlap,0.95);   %功率谱估计,并以0.95的置信度给出置信区间,无返回值是绘制出置信区间
figure
plot(f,10*log10(Pxx));  %绘制功率谱
xlabel('频率/Hz');ylabel('功率谱/dB');
title('PSD—Welch方法'); 
grid on

利用welch法估计两个信号的互功率谱密度CSD,函数调用格式为:

    [Pxy[,f]]=csd(x,y,Nfft,Fs,window,Noverlap,’dflag’)

    [Pxy,Pxyc,f]=csd(x,y,Nfft,Fs,window,Noverlap,p)

这里,x,y为两个信号序列;Pxy为x,y的互功率谱估计;其他参数的意义同自功率谱函数psd。

5. 多窗口法MTM功率谱估计及其MATLAB函数  

       多窗口法利用多个正交窗口(Tapers)获得各自独立的近似功率谱估计,然后综合这些估计得到一个序列的功率谱估计。相对于普通的周期图法,这种功率谱估计具有更大的自由度,并在估计精度和估计波动方面均有较好的效果。普通的功率谱估计只利用单一窗口,因此在序列始端和末端均会丢失相关信息,而且无法找回。而MTM法估计增加窗口使得丢失的信息尽量减少。

      MTM法简单地采用一个参数:时间带宽积(Time-bandwidth product)NW,这个参数用以定义计算功率谱所用窗的数目,为2*NW-1。NW越大,功率谱计算次数越多,时间域分辨率越高,而频率域分辨率降低,使得功率谱估计的波动减小。随着NW增大,每次估计中谱泄漏增多,总功率谱估计的偏差增大。对于每一个数据组,通常有一个最优的NW使得在估计偏差和估计波动两方面求得折中,这需要在程序中反复调试来获得。

MATLAB信号处理工具箱中函数PMTM就是采用MTM法估计功率谱密度。函数调用格式为:

[Pxx,f]=pmtm(x,nw,Nfft,Fs)

式中,x为信号序列;

nw为时间带宽积,缺省值为4。通常可取2,5/2,3,7/2;

Nfft为快速傅里叶变换长度;

Fs为采样频率。

%% pmtm(多窗口法)功率谱估计
fs=128;sigLength=1152;                  %采样频率、数据点数
Nfft=1024;n=0:sigLength-1;t=n/fs;       %傅里叶变换点数,时间序列
nw=4;                                   %为时间带宽积,缺省值为4
[Pxx1,f]=pmtm(x_sigal(:,1),nw,Nfft,fs); %用多窗口法(NW=4)估计功率谱
figure;
plot(f,10*log10(Pxx1));                 %绘制功率谱
xlabel('频率/Hz');ylabel('功率谱/dB');
title('多窗口法(MTM) 功率谱求解');
grid on;

函数还可以通过无返回值而绘出置信区间,如pmtm(x,nw,Nfft,Fs,’option’,p)绘制带置信区间的功率谱密度估计曲线,0<=p<=1。

6 . 最大熵法pmem功率谱估计

      周期图法功率谱估计需要对信号序列“截断”或加窗处理,其结果是使估计的功率谱密度为信号序列真实谱和窗谱的卷积,导致误差的产生。最大熵功率谱估计的目的是最大限度地保留截断后丢失的“窗口”以外信号的信息,使估计谱的熵最大。主要方法是以已知的自相关序列rxx(0),rxx(1),…,rxx(p)为基础,外推自相关序列rxx(p+1),rxx(p+2),…,保证信息熵最大。

最大熵功率谱估计法假定随机过程是平稳高斯过程,可以证明,随机信号的最大熵谱与AR自回归(全极点滤波器)模型谱是等价的。

MATLAB信号处理工具箱提供最大熵功率谱估计函数pmem,其调用格式为:

[Pxx,f]=pmem(x,p,Nfft,Fs)

式中,x为输入信号序列或输入相关矩阵;

p为全极点滤波器阶次;

%% pmem(最大熵法)功率谱估计

sigLength=1152;     %数据长度
Nfft=1024;          %傅里叶变换点数(一般为数据点数临近的2的n次方,或者直接取数据点数)
fs=128;             %采样频率
p=6;                %全极点滤波器阶次
n=0:sigLength-1;
t=n/fs;             %时间序列
[Pxx1,f]=pmem(x_sigal(:,1),p,Nfft,fs);   %采用最大熵法,采用滤波器阶数6,估计功率谱
figure;	
plot(f,10*log10(Pxx1));                  %绘制功率谱
xlabel('频率/Hz');ylabel('功率谱/dB');
title('最大熵法 Order=20原始信号功率谱');
grid on

7 .多信号分类法功率谱估计

MATLAB信号处理工具箱还提供另一种功率谱估计函数pmusic。该函数执行多信号分类法(multiple signal classification, Music法)。将数据自相关矩阵看成由信号自相关矩阵和噪声自相关矩阵两部分组成,即数据自相关矩阵R包含有两个子空间信息:信号子空间和噪声子空间。这样,矩阵特征值向量(Eigen vector)也可分为两个子空间:信号子空间和噪声子空间。为了求得功率谱估计,函数pmusic计算信号子空间和噪声子空间的特征值向量函数,使得在周期信号频率处函数值最大,功率谱估计出现峰值,而在其他频率处函数值最小。其调用格式为:

[Pxx,f,a]=pmusic(x, p ,Nfft, Fs, window, Noverlap)

式中,x为输入信号的向量或矩阵;p为信号子空间维数;其他参数的意义与函数psd相同。

%% pmusic(多信号分类法)功率谱估计
fs=128;sigLength=1152;             %采样频率、数据长度
window=hanning(256);               %选用的窗口大小
noverlap=128;                      %分段序列重叠的采样点数(长度)
Nfft=1024;n=0:sigLength-1;t=n/fs;  %傅里叶变换点数,时间序列
[Pxx,f,a]=pmusic(x_sigal(:,1),[7,1.1],Nfft,fs,window,noverlap);   %采用多信号分类法估计功率谱
figure;
plot(f,10*log10(Pxx));                                            %绘制功率谱
xlabel('频率/Hz'); ylabel('功率谱/dB')
title('通过MUSIC法估计的伪谱')

特别说明:x_sigal(:,1)我使用的脑电运动想象数据作为输入数据

供大家参考网址:

 https://wenku.baidu.com/view/7046318b0b1c59eef9c7b451.html