在 python 中应用巴特沃斯带通滤波器后,如何去除信号开头的大尖峰?

how do I remove large spike at the beginning of signal after applying Butterworth Bandpass filter in python?

我想使用带通滤波器去除信号趋势,所以我在 python 中使用了 FL=0.1 Hz 和 FH=20Hz 的 Butterworth 滤波器,但在应用此带通滤波器后,我在开始时观察到一个大尖峰我的信号。 这个尖峰是做什么用的?以及如何消除 python 中的这个尖峰?

您可以从 this link 下载“data1.csv”。

from scipy.signal import butter, lfilter
from numpy import genfromtxt
import numpy as np
import matplotlib.pyplot as plt

def butter_bandpass(lowcut, highcut, fs, order=5):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='band')
    return b, a

def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
    b, a = butter_bandpass(lowcut, highcut, fs, order=order)
    y = lfilter(b, a, data)
    return y


BP_without_NaN = genfromtxt('data1.csv', delimiter=',')
framerate=1024

# detrending [0.1Hz  20Hz]
OMW = butter_bandpass_filter(data = BP_without_NaN, lowcut = 0.1, highcut = 20 , fs = framerate, order = 3)

# plot OMW
time = np.linspace(0, len(OMW)/framerate ,len(OMW))
plt.plot(time, OMW)
plt.show()

应用 Butterworth(或任何 IIR)滤波器时,每个输出样本都是根据先前的输出样本计算的,

y[n] = b0 * x[n] + b1 * x[n-1] + ... + bk * x[n-k]
                 - a1 * y[n-1] + ... + ak * y[n-k]

这对如何在信号开始时启动滤波器造成了问题,因为尚未计算输出样本。处理此问题的一种典型方法是假设负时间 n < 0 的所有输出均为零,或者等价地,从概念上将输入推断为零。这种零初始化方法是 scipy.signal.lfilter 默认情况下所做的。

但是,这种方法并不总是合适的。如果输入信号没有开始接近零,则外推零点会在信号中引入人为阶跃或跳跃不连续性,并且输出信号将以不需要的瞬态开始,即滤波器对此人为阶跃的响应。

查看您的链接数据,输入以几百个样本开始,等于 154。这解释了绘图开始时的大尖峰。您基本上可以通过更改过滤器初始化来消除尖峰。使用 scipy.signal.lfilter_zi 计算 lfilter 的阶跃响应稳态值 154 的初始条件:

zi = lfilter_zi(b, a) * data[0]

然后与 lfilter 一起使用 y, _ = lfilter(b, a, data, zi=zi)。这是我通过此更改得到的结果: