我正在尝试在Python中执行EEG信号的FFT,然后根据带宽确定它是alpha还是beta信号。它看起来很好,但结果图不是他们应该的,频率和幅度值不是我预期的。任何帮助表示赞赏,这是代码:
from scipy.io import loadmat
import scipy
import numpy as np
from pylab import *
import matplotlib.pyplot as plt
eeg = loadmat("eeg_2013.mat");
eeg1=eeg['eeg1'][0]
eeg2=eeg['eeg2'][0]
fs = eeg['fs'][0][0]
fft1 = scipy.fft(eeg1)
f = np.linspace (fs,len(eeg1), len(eeg1), endpoint=False)
plt.figure(1)
plt.subplot(211)
plt.plot (f, abs (fft1))
plt.title ('Magnitude spectrum of the signal')
plt.xlabel ('Frequency (Hz)')
show()
plt.subplot(212)
fft2 = scipy.fft(eeg2)
f = np.linspace (fs,len(eeg2), len(eeg2), endpoint=False)
plt.plot (f, abs (fft2))
plt.title ('Magnitude spectrum of the signal')
plt.xlabel ('Frequency (Hz)')
show()
答案 0 :(得分:3)
为了得到fft频率的数组,你应该使用fftfreq;它为您提供了一系列用作absciss的频率:
from scipy.fftpack import fftfreq
eeg = loadmat("eeg_2013.mat");
eeg1=eeg['eeg1'][0]
eeg2=eeg['eeg2'][0]
fs = eeg['fs'][0][0]
fft1 = scipy.fft(eeg1)
f=fftfreq(eeg1.size,1/fs)
很抱歉,我无法在实际情况下测试此代码,因为您没有发布数据样本,但我希望这可行。
关于如何确定带宽,据我所知,您希望获得基频。无论您的信号是否有噪声,都有不同的方式,或多或少复杂,......在您的情况下,您只想知道基频f0是否在8-13Hz(alpha)或13-30Hz(beta)范围内);一个非常简单的方法是计算8-13Hz范围内fft的最大值:fft1[(f>8) & (f<13)].max()
如果它超过1000比例,它就是一个alpha波,否则就是beta。如果您的信号不太相似,请发布一些不同类型的样本示例和结果,以便我们可以尝试更复杂的算法。
答案 1 :(得分:2)
如果您的采样频率为fs
并且您有N=len(eeg1)
个样本,那么fft
过程当然会返回N
个值的数组。它们中的第一个N/2
对应于频率范围0..fs/2
,频率的后半部分对应于镜像频率范围-fs/2..0
。对于实际输入信号,镜像半部分只是正半部分的复共轭,因此在进一步分析中可以忽略它(但不能在反fft中)。
基本上,你应该格式化
f=linspace(0,N-1,N)*fs/N
编辑:或者更简单,只需对初始代码进行最少的更改
f = np.linspace (0,fs,len(eeg1), endpoint=False)
所以f
的范围从0
到fs
之前,并忽略输出中fft结果的后半部分:
plt.plot( f(0:N/2), abs( fft1(0:N/2) ) )
补充:您可以使用fftshift交换两半,然后正确的频率范围是
f = np.linspace (-fs/2,fs/2,len(eeg1), endpoint=False)