scipy 如何在Python中对信号应用滤波器

zf2sa74q  于 2023-08-05  发布在  Python
关注(0)|答案(2)|浏览(125)

python中是否有任何准备好的函数来对给定信号应用滤波器(例如巴特沃思滤波器)?我在'scipy.signal'中寻找这样一个函数,但是我没有找到比滤波器设计更有用的函数。实际上我想用这个函数来卷积一个滤波器和信号。

ewm0tg9j

ewm0tg9j1#

是的!有两个:

scipy.signal.filtfilt
scipy.signal.lfilter

字符串
还有一些卷积方法(convolvefftconvolve),但这些方法可能不适合您的应用,因为它涉及IIR滤波器。
完整代码示例:

b, a = scipy.signal.butter(N, Wn, 'low')
output_signal = scipy.signal.filtfilt(b, a, input_signal)


您可以在文档中阅读有关参数和用法的更多信息。其中一个问题是Wn是奈奎斯特频率的一部分(采样频率的一半)。因此,如果采样速率为1000 Hz,而您希望截止频率为250 Hz,则应使用Wn=0.5
顺便说一句,我强烈推荐在大多数应用程序中使用filtfilt而不是lfilter(在Matlab中称为filter)。如documentation所述:
此函数应用线性滤波器两次,一次向前,一次向后。组合滤波器具有线性相位。
这意味着,每个输出值都是输入中“过去”和“未来”点的函数。因此,它不会滞后于输入。
相反,lfilter只使用输入的“过去”值。这不可避免地引入了时间滞后,这将是频率相关的。当然,也有一些应用程序需要这样做(特别是实时过滤),但大多数用户使用filtfilt要好得多。

mbyulnm0

mbyulnm02#

虽然@cxrodgers的答案中的解释对于无限脉冲响应(IIR)滤波器是正确的(巴特沃思是这种滤波器类型的一个例子)。在“如何在python中对信号应用过滤器”中有更多到目前为止已经回答的内容。我认为需要一些理论上的解释,这样没有经验的人在阅读公认的答案时就不会认为在Python中滤波时总是应用scipy.signal.filtfilt总是正确的解决方案,而对于有限脉冲响应(FIR)滤波器来说,这是不必要的。
可实现的(可以在实践中实现的)IIR滤波器总是具有非线性相位。这意味着不同频率分量在其输入端的输入顺序将在其输出端发生偏移(我认为@cxrodgers将此称为“滞后输入”)。已经证明,IIR滤波器理论上可以具有线性相位,但是系数将需要是无理的,因此这是不可实现的。更多信息here
作为补偿这种非线性相位效应的一种方式,scipy.signal.filtfilt应用称为zero-phase filtering的方法,该方法在一个方向上应用IIR滤波器,然后将其反转并再次应用,从而在第二次通过中补偿在第一次通过中引入的非线性。此过程需要额外的时间,因此在处理真实的应用程序时可能不可行(这取决于与新数据到来的速度相比,您执行两个过滤操作的速度)
然而,FIR滤波器通常被设计成具有线性相位(这意味着其系数在时间上围绕中心系数对称,即,第一系数与最后一个系数相同; the second is the same as the next to-last,etc)更多信息here
因此,在Python中应用FIR滤波器时,唯一正确的答案是使用scipy.signal.lfilter。不需要再次补偿已经线性的相位。请参见以下应用带通Kaiser FIR滤波器的示例。更多示例here

import numpy as np
from scipy import signal as sp_signal

#defining parameters
Fs = 48000
duration = 1 #seconds
time = np.arange(0,duration,1/Fs)
cols = time.size
np.random.seed(0)

# defining signals
sig_mean = 0
sig_std = 1 

sig1 = np.random.normal(sig_mean, sig_std, cols)

# band pass Kaiser FIR filtering
ntaps = 128
width = 1.0 
nyq = 0.5*Fs
atten = sp_signal.kaiser_atten(numtaps=ntaps,width=width/nyq) #desired width of the transition region between passband and stopband expressed as a fraction of the Nyquist frequency
beta = sp_signal.kaiser_beta(atten)
b = sp_signal.firwin(numtaps=ntaps,cutoff=[1000, 2000],nyq=nyq,pass_zero=False,window=('kaiser', beta), scale=False)
a = 1

# filtered signal
sig2 = sp_signal.lfilter(b, a, sig1)

字符串

相关问题