Python中的FFT滤波器与lfilter的比较

2 投票
1 回答
2209 浏览
提问于 2025-04-17 05:47

我在用Python给信号加带通滤波器的时候遇到了一些麻烦。我尝试了以下两种方法:

  • 手动做一个方框窗口,也就是先对信号进行快速傅里叶变换(FFT),然后用方框窗口来滤波,最后再用逆快速傅里叶变换(IFFT)把结果转换回时间域。
  • 使用scipy.signal模块,利用firwin2来构建滤波器,然后用lfilter来进行滤波。

此外,我还在音频处理软件Cool Edit中做了同样的滤波,并把上面两种测试的结果进行了比较。

从结果来看(我还是新手,所以不能发我的png图),FFT和scipy.signal的结果差别很大。与Cool Edit的结果相比,FFT的结果比较接近,但并不完全相同。代码如下:

# imports 
from pylab import *
import os
import scipy.signal as signal

# load data 
tr=loadtxt('tr6516.txt',skiprows=1)

sr = 500            # [samples/s]
nf = sr/2.0         # Nyquist frequence
W = 512            # Window widht for filtering
N=float(8192)       # Fourier settings
Ns = len(tr[:,0])   # Total number of samples

# Create inpulse responce from the filter
fv=12.25
w    =0.5
r    =0.5*w
Hz=[0, fv-w-r, fv-w, fv+w, fv+w+r, nf]
ff=[0, 0,      1,    1,    0,      0]
b = signal.firwin2(W,Hz,ff,nfreqs=N+1,nyq=nf)
SigFilter = signal.lfilter(b, 1, tr[:,1])

# Fourier transform
X1 = fft(tr[:,1],n=int(N))
X1 = fftshift(X1)
F1 = arange(-N/2.0,N/2.0)/N*sr

# Filter data
ff=[0,1,1,0]
fv=12.25
w    =0.5
r    =0.5*w
Hz=[fv-w-r,fv-w,fv+w,fv+w+r]
k1=interp(-F1,Hz,ff)+interp(F1,Hz,ff)
X1_f=X1*k1
X1_f=ifftshift(X1_f)
x1_f=ifft(X1_f,n=int(N))

有没有人能告诉我为什么会有这样的差异?在Cool Edit中进行的滤波和在scipy.signal中的设置是一样的(汉宁窗口,窗口宽度512)。还是说我完全搞错了。

最好的祝福,
Anders

上面的代码:

enter image description here

与Cool Edit的比较:

enter image description here

enter image description here

1 个回答

0

小的差异可以用不同的库使用不同的算法来解释,这些算法在累积误差时略有不同。

举个例子,如果你用三种不同的方法来计算离散傅里叶变换(DFT),分别是基于2的快速傅里叶变换(FFT)、分裂基快速傅里叶变换和普通的DFT,结果都会有一点点不同。实际上,普通的DFT准确度比所有不错的FFT实现都要差,因为它使用了更多的浮点运算,因此累积的误差也更多。

这是否能解释你看到的结果接近(但不完全相同)的情况呢?

撰写回答