我尝试的是用 fft 过滤我的数据。我有一个以 500Hz 作为一维阵列记录的噪声信号。我的高频应该用 20Hz 截止,我的低频应该用 10Hz 截止。我尝试过的是:
fft=scipy.fft(signal)
bp=fft[:]
for i in range(len(bp)):
if not 10<i<20:
bp[i]=0
ibp=scipy.ifft(bp)
我现在得到的是复数。所以一定有什么地方不对劲。什么?如何更正我的代码?
我尝试的是用 fft 过滤我的数据。我有一个以 500Hz 作为一维阵列记录的噪声信号。我的高频应该用 20Hz 截止,我的低频应该用 10Hz 截止。我尝试过的是:
fft=scipy.fft(signal)
bp=fft[:]
for i in range(len(bp)):
if not 10<i<20:
bp[i]=0
ibp=scipy.ifft(bp)
我现在得到的是复数。所以一定有什么地方不对劲。什么?如何更正我的代码?
值得注意的是,您的单位的大小bp
不一定以赫兹为单位,而是取决于信号的采样频率,您应该scipy.fftpack.fftfreq
用于转换。此外,如果您的信号是真实的,您应该使用scipy.fftpack.rfft
. 这是一个最小的工作示例,它过滤掉所有小于指定数量的频率:
import numpy as np
from scipy.fftpack import rfft, irfft, fftfreq
time = np.linspace(0,10,2000)
signal = np.cos(5*np.pi*time) + np.cos(7*np.pi*time)
W = fftfreq(signal.size, d=time[1]-time[0])
f_signal = rfft(signal)
# If our original signal time was in seconds, this is now in Hz
cut_f_signal = f_signal.copy()
cut_f_signal[(W<6)] = 0
cut_signal = irfft(cut_f_signal)
我们可以绘制信号在实数和傅立叶空间中的演变:
import pylab as plt
plt.subplot(221)
plt.plot(time,signal)
plt.subplot(222)
plt.plot(W,f_signal)
plt.xlim(0,10)
plt.subplot(223)
plt.plot(W,cut_f_signal)
plt.xlim(0,10)
plt.subplot(224)
plt.plot(time,cut_signal)
plt.show()
您在这里尝试做的事情存在一个根本缺陷-您在频域中应用了一个矩形窗口,这将产生一个与 sinc 函数卷积的时域信号。换句话说,由于您在频域中引入的阶跃变化,时域信号中会出现大量“振铃”。进行这种频域滤波的正确方法是在频域中应用合适的窗函数。任何好的介绍性 DSP 书籍都应该涵盖这一点。