您好,登录后才能下订单哦!
本篇内容介绍了“FFT频谱分析原理与python的实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
点击上面"脑机接口社区"关注我们
频谱分析
下面是一组用于描述和解释信号属性的常用量(matlab的常见形式,python中的常见形式也类似):
x: 采样的数据;
n=length(x): 样本数量;
fs: 采样频率(每单位时间或空间的样本数)(单位常用:赫兹Hz);
dt=1/fs :每样本的时间或空间增量(如果是时间上的增量,则又称:采样间隔或采样步长,单位常用:s);
t=(0:n-1)/fs : 数据的时间或空间范围;
y=fft(x) : 数据的离散傅里叶变换(DFT);
abs(y) :DFT的振幅;
(abs(y).^2)/n :DFT的幂;
fs/n : 频率增量;
f=(0:n-1) * (fs/n) : 频率范围;
fs/2 :Nyquist频率(频率范围的中点);
频谱分析是一种将复噪声号分解为较简单信号的技术。真实世界中的信号可能由多种简单信号叠加而成。找出一个信号在不同频率下的信息(可能是幅度、功率、强度或相位等)的作法就是频谱分析。
采样定理:采样频率要大于信号频率的两倍。
N个采样点经过FFT变换后得到N个点的以复数形式记录的FFT结果。
假设采样频率为Fs,采样点数为N。那么FFT运算的结果就是N个复数(或N个点),每一个复数就对应着一个频率值以及该频率信号的幅值和相位。
第一个点对应的频率为0Hz(即直流分量),最后一个点N的下一个点对应采样频率Fs。其中任意一个采样点n所代表的信号频率:
这表明,频谱分析得到的信号频率最大为 (N-1)*Fs/N,对频率的分辨能力是Fs/N。采样频率和采样时间制约着通过FFT运算能分析得到的信号频率上限,同时也限定了分析得到的信号频率的分辨率。
每一个复数的模值对应该点所对应的频率值的幅度特性,具体的定量关系如下:
假设信号由以下周期的原始信号叠加而成:
那么,在经过FFT分析后得到的第一个点的模值是A1的N倍,而且只有在FFT结果点对应的频率在ω2,ω3时,其模值才明显放大,在其他频率点,模值接近于0。在这些模值明显放大的点中,除第一个点之外的其它点模值是相应信号幅值的N/2倍。
每个复数的相位就是在该频率值下信号的相位:φ2,φ3。
FFT结果有对称性,通常我们只是用前半部分的结果,也就是小于采样频率一半的结果。同时也只有采样频率一半以内、具有一定幅值的信号频率才是真正的信号频率。
案例1
import numpy as npimport pylab as plimport math# 采样频率fs=1048# 采样步长t = [x/1048.0 for x in range(1048)]"""设计的采样值假设信号y由4个周期信号叠加所得,如下所示"""y = [ 3.0 * np.cos(2.0 * np.pi * 50 * t0 - np.pi * 30/180) + 1.5 * np.cos(2.0 * np.pi * 75 * t0 + np.pi * 90/180) + 1.0 * np.cos(2.0 * np.pi * 150 * t0 + np.pi * 120/180) + 2.0 * np.cos(2.0 * np.pi * 220 * t0 + np.pi * 30/180) for t0 in t ]pl.plot(t,y)pl.xlabel('time(s)')pl.title("original signal")pl.show()
"""现在对上述信号y在0-1秒时间内进行频谱分析,本案例中采样频率为1048Hz,即单位时间内采样点数为1048"""# 采样点数N=len(t)# 采样频率fs=1048.0# 分辨率df = fs/(N-1)# 构建频率数组f = [df*n for n in range(0,N)]Y = np.fft.fft(y)*2/N #*2/N 反映了FFT变换的结果与实际信号幅值之间的关系absY = [np.abs(x) for x in Y] #求傅里叶变换结果的模pl.plot(f,absY)pl.xlabel('freq(Hz)')pl.title("fft")pl.show()
案例2
from scipy.fftpack import fft, fftshift, ifftfrom scipy.fftpack import fftfreqimport numpy as npimport matplotlib.pyplot as plt%matplotlib inline"""t_s:采样周期t_start:起始时间t_end:结束时间"""t_s = 0.01t_start = 0.5t_end = 5t = np.arange(t_start, t_end, t_s)f0 = 5f1 = 20# 绘制图表plt.figure(figsize=(10, 12))# 构建原始信号序列y = 1.5*np.sin(2*np.pi*f0*t) + 3*np.sin(2*np.pi*20*t) + np.random.randn(t.size)ax=plt.subplot(511)ax.set_title('original signal')plt.tight_layout()plt.plot(y)"""FFT(Fast Fourier Transformation)快速傅里叶变换"""Y = fft(y)ax=plt.subplot(512)ax.set_title('fft transform')plt.plot(np.abs(Y))"""Y = fftshift(X) 通过将零频分量移动到数组中心,重新排列傅里叶变换 X。"""shift_Y = fftshift(Y)ax=plt.subplot(513)ax.set_title('shift fft transform')plt.plot(np.abs(shift_Y))"""得到正频率部分"""pos_Y_from_fft = Y[:Y.size//2]ax=plt.subplot(514)ax.set_title('fft transform')plt.tight_layout()plt.plot(np.abs(pos_Y_from_fft))"""直接截取 shift fft结果的前半部分"""pos_Y_from_shift = shift_Y[shift_Y.size//2:]ax=plt.subplot(515)ax.set_title('shift fft cut')plt.plot(np.abs(pos_Y_from_shift))plt.show()
众所周知,傅里叶变换的快速算法FFT可以用来对信号的频域特征进行分析,然而,FFT仅能用于平稳信号的分析,对于非平稳信号,则需要采用短时傅里叶变换(STFT)进行分析。
对于非平稳信号,短时傅里叶变换所采用的策略是在信号上面加窗,一般是hamming窗,当然也可以是其它类型的窗函数,加窗之后的信号被分割为一组短长度子序列,子序列可以近似的看为平稳序列,可以用傅里叶变换的方式去进行分析,这也是短时傅里叶变换的精髓所在。
用STFT进行脑电信号分析一般有两种思路,第一种是用STFT来分离EEG信号的波段,从而求得每一个波段的能量作为特征(alpha、beta、theta、gamma、deta)。第二种是利用STFT计算功率谱密度作为特征,功率谱密度(PSD)特征可以针对整个信号子序列也可以针对子序列中特定的波段来计算。这两种思路中,第二种思路用的比较广,下面对其进行说明。
matlab中进行STFT的函数为spectrogram,计算功率谱密度(PSD)时使用如下格式:
[S,F,T,P]=spectrogram(x,window,noverlap,nfft,fs)
其中,S为输入信号x的短时傅里叶变换,F为频率向量,T为时间向量,P为功率谱密度矩阵,x为输入信号,window为时间窗,noverlap为overlap的点数,如果为0就是没有overlap,nfft为DFT的点数,fs为采样频率。其中,F向量的维度和P的行数一致,可以根据F向量来选取特定波段的PSD,还可以将alpha、beta、theta、gamma、deta这几个波段分别分为几个窄波段,提取窄带PSD。
“FFT频谱分析原理与python的实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。