在scipy.signal中应用过滤器:使用lfilter还是filtfilt?


21

我在SO线程中看到了一个建议使用filtfilt该建议,而不是执行向后/向前过滤lfilter

相对于另一种技术使用一种动机是什么?


Filtfilt较慢
Aaron


1
@Aaron filtfilt在相同的方向上执行lfilter两次相同的滤波器,因此它不会比在一个方向上执行两次更慢,这就是您获得相同频率响应的方式。
endlith 2014年

是的,这就是我的意思。它慢了一倍。
亚伦

我对此并不陌生,一直在寻找使用filtfilt的方法。@endolith表示scipy.signal使用原始信号。我不确定原始信号是什么意思以及我们如何得到它。我有一个wav文件,可以将其加载到系统中,但是我认为它不是原始信号,因为它被分解为一个numpy数组和样本数。请有人帮忙。谢谢!
Arunima Pathania

Answers:


30
  • filtfilt是零相位滤波,它不会在滤波时移动信号。由于在所有频率下相位均为零,因此它也是线性相位。向后过滤需要您预测未来,因此不能将其用于“在线”现实应用中,而只能用于信号记录的脱机处理。

  • lfilter仅是因果关系的实时过滤,类似于实际的电子过滤器。不能为零相。它可以是线性相位(对称FIR),但通常不是。通常,它会在不同的频率上增加不同的延迟量。

一个例子和图像应该使它显而易见。尽管滤波器的频率响应幅度相同(左上和右上),但零相位低通与原始信号对齐,只是没有高频成分,而最小相位滤波则以因果关系延迟了信号:

filtfilt与lfilter

from __future__ import division, print_function
import numpy as np
from numpy.random import randn
from numpy.fft import rfft
from scipy import signal
import matplotlib.pyplot as plt

b, a = signal.butter(4, 0.03, analog=False)

# Show that frequency response is the same
impulse = np.zeros(1000)
impulse[500] = 1

# Applies filter forward and backward in time
imp_ff = signal.filtfilt(b, a, impulse)

# Applies filter forward in time twice (for same frequency response)
imp_lf = signal.lfilter(b, a, signal.lfilter(b, a, impulse))

plt.subplot(2, 2, 1)
plt.semilogx(20*np.log10(np.abs(rfft(imp_lf))))
plt.ylim(-100, 20)
plt.grid(True, which='both')
plt.title('lfilter')

plt.subplot(2, 2, 2)
plt.semilogx(20*np.log10(np.abs(rfft(imp_ff))))
plt.ylim(-100, 20)
plt.grid(True, which='both')
plt.title('filtfilt')

sig = np.cumsum(randn(800))  # Brownian noise
sig_ff = signal.filtfilt(b, a, sig)
sig_lf = signal.lfilter(b, a, signal.lfilter(b, a, sig))
plt.subplot(2, 1, 2)
plt.plot(sig, color='silver', label='Original')
plt.plot(sig_ff, color='#3465a4', label='filtfilt')
plt.plot(sig_lf, color='#cc0000', label='lfilter')
plt.grid(True, which='both')
plt.legend(loc="best")

4
lfilter不一定是最小相位,它可以是任何东西,具体取决于滤波器系数,但是在任何情况下都是因果关系filtfilt不是。因此,filtfilt具有零延迟并lfilter始终添加一些延迟的比较结果并不完全正确,因为filtfilt这首先是无因果的。真正重要的是filtfilt不会引起任何相位失真,lfilter反而会引起相位失真(除非它用作线性相位FIR滤波器,即分母= 1)。
Matt L.

还值得注意的是,用过滤第N阶filtfilt对应于用过滤第(2N-1)阶lfilter
Thomas Arildsen

@ThomasArildsen不只是2N吗?这就是我在脚本中展示的内容
endolith,2014年

@ArunimaPathania您应该在我的回答下而不是在问题下发表评论。“原始信号”仅表示您要过滤的信号。您可以使用lfilter或进行过滤filtfilt。如图所示,它们的行为有所不同
endolith '18

7

@endolith的回答是完整而正确的!请先阅读他的文章,然后再阅读此文章。由于我的声誉低下,我无法回复@Thomas Arildsen@endolith争论通过filtfilt以下方式获得的有效过滤器顺序的评论:

  • lfilter 确实应用给定的滤波器,并且在傅立叶空间中,这就像应用滤波器传递函数ONCE一样。

  • filtfilt两次应用相同的滤镜,效果就像应用滤镜传递函数SQUARED一样。对于scipy.signal.butter具有传递函数的巴特沃斯滤波器()

G(n)=11ω2nwhere n is order of filter

有效收益为

G(n)filtfilt=G(n)2=11ω2n

2n2n1

G(n)filtfiltG(2n).

1
请尽量不要添加评论作为答案。但是,欢迎来到SE.DSP,并向我+1。我认为这增加了答案...至少尝试让足够多的代表发表评论!:-)
彼得·K。

我不认为这是真的。G(n)是滤波器的幅度增益。如果您将复数传递函数级联,我认为它将达到2n。
Mike

我通过快速仿真证实了,一个6阶巴特沃斯给出的G(ω)与2 x(3阶巴特沃思)级联时相同,但是3阶截止频率按1.6缩放。除了截止频率的缩放比例之外,结果是相同的。因此,阶数确实会以2n缩放,但请注意,级联时通带会减少,需要补偿。有人可以随意解释理论,但我真的不希望通过所有数学课程。
麦克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.