scipy.signal.

filtfilt#

scipy.signal.filtfilt(b, a, x, axis=-1, padtype='odd', padlen=None, method='pad', irlen=None)[源代码][源代码]#

对信号进行前向和后向数字滤波。

此函数应用一个线性数字滤波器两次,一次正向,一次反向。组合滤波器具有零相位,并且滤波器阶数是原始滤波器的两倍。

该函数提供了处理信号边缘的选项。

函数 sosfiltfilt`(以及使用 ``output=’sos’` 进行滤波器设计)在大多数滤波任务中应优先于 filtfilt,因为二阶节段具有较少的数值问题。

参数:
b(N,) 数组类

滤波器的分子系数向量。

a(N,) 数组类

滤波器的分母系数向量。如果 a[0] 不是 1,那么 ab 都会被 a[0] 归一化。

xarray_like

要过滤的数据数组。

int, 可选

应用过滤器的 x 轴。默认值为 -1。

padtypestr 或 None, 可选

必须是 ‘odd’, ‘even’, ‘constant’, 或 None。这决定了应用于填充信号的滤波器使用的扩展类型。如果 padtype 是 None,则不使用填充。默认值是 ‘odd’。

padlenint 或 None, 可选

在应用滤波器之前,在 axis 的两侧扩展 x 的元素数量。此值必须小于 x.shape[axis] - 1padlen=0 表示没有填充。默认值为 3 * max(len(a), len(b))

方法str, 可选

确定处理信号边缘的方法,可以是“pad”或“gust”。当 method 为“pad”时,信号被填充;填充类型由 padtypepadlen 决定,irlen 被忽略。当 method 为“gust”时,使用Gustafsson的方法,padtypepadlen 被忽略。

irlenint 或 None, 可选

method 为 “gust” 时,irlen 指定滤波器脉冲响应的长度。如果 irlen 为 None,则不忽略脉冲响应的任何部分。对于长信号,指定 irlen 可以显著提高滤波器的性能。

返回:
yndarray

x 形状相同的过滤输出。

注释

method 为 “pad” 时,函数会沿着给定的轴以三种方式之一填充数据:奇数、偶数或常数。奇数和偶数扩展在数据的终点处具有相应的对称性。常数扩展使用终点处的值来扩展数据。在正向和反向传递中,滤波器的初始条件通过使用 lfilter_zi 并根据扩展数据的终点进行缩放来找到。

method 为 “gust” 时,使用 Gustafsson 方法 [1]。初始条件为前向和后向传递选择,以便前向后向滤波器与后向前向滤波器给出相同的结果。

在 scipy 版本 0.16.0 中添加了使用 Gustaffson 方法的选项。

参考文献

[1]

F. Gustaffson, “Determining the initial states in forward-backward filtering”, Transactions on Signal Processing, Vol. 46, pp. 988-992, 1996.

示例

示例将使用 scipy.signal 中的几个函数。

>>> import numpy as np
>>> from scipy import signal
>>> import matplotlib.pyplot as plt

首先,我们创建一个持续一秒的信号,该信号是两个纯正弦波的总和,频率分别为5 Hz和250 Hz,采样频率为2000 Hz。

>>> t = np.linspace(0, 1.0, 2001)
>>> xlow = np.sin(2 * np.pi * 5 * t)
>>> xhigh = np.sin(2 * np.pi * 250 * t)
>>> x = xlow + xhigh

现在创建一个截止频率为奈奎斯特频率的0.125倍,即125 Hz的低通巴特沃斯滤波器,并使用 filtfilt 将其应用于 x。结果应近似于 xlow,且无相位偏移。

>>> b, a = signal.butter(8, 0.125)
>>> y = signal.filtfilt(b, a, x, padlen=150)
>>> np.abs(y - xlow).max()
9.1086182074789912e-06

对于这个人工示例,我们得到了一个相当干净的结果,因为奇怪的扩展是精确的,并且由于适度的填充长度,滤波器的瞬态在实际数据到达时已经消散。通常,边缘的瞬态效应是不可避免的。

以下示例展示了选项 method="gust"

首先,创建一个过滤器。

>>> b, a = signal.ellip(4, 0.01, 120, 0.125)  # Filter to be applied.

sig 是一个待滤波的随机输入信号。

>>> rng = np.random.default_rng()
>>> n = 60
>>> sig = rng.standard_normal(n)**3 + 3*rng.standard_normal(n).cumsum()

sig 应用 filtfilt,一次使用 Gustafsson 方法,一次使用填充方法,并绘制结果进行比较。

>>> fgust = signal.filtfilt(b, a, sig, method="gust")
>>> fpad = signal.filtfilt(b, a, sig, padlen=50)
>>> plt.plot(sig, 'k-', label='input')
>>> plt.plot(fgust, 'b-', linewidth=4, label='gust')
>>> plt.plot(fpad, 'c-', linewidth=1.5, label='pad')
>>> plt.legend(loc='best')
>>> plt.show()
../../_images/scipy-signal-filtfilt-1_00_00.png

irlen 参数可以用来提高 Gustafsson 方法的性能。

估计滤波器的脉冲响应长度。

>>> z, p, k = signal.tf2zpk(b, a)
>>> eps = 1e-9
>>> r = np.max(np.abs(p))
>>> approx_impulse_len = int(np.ceil(np.log(eps) / np.log(r)))
>>> approx_impulse_len
137

将滤波器应用于更长的信号,无论是否使用 irlen 参数。y1y2 之间的差异很小。对于长信号,使用 irlen 可以显著提高性能。

>>> x = rng.standard_normal(4000)
>>> y1 = signal.filtfilt(b, a, x, method='gust')
>>> y2 = signal.filtfilt(b, a, x, method='gust', irlen=approx_impulse_len)
>>> print(np.max(np.abs(y1 - y2)))
2.875334415008979e-10