使用Python在原始信号上应用合适的Butterworth滤波器

时间:2018-08-27 22:16:22

标签: python scipy signal-processing digital-filter butterworth

我已经从TI AFE4490获得了10秒的原始PPG(光电容积描记图)信号。我的硬件已经过校准,我每秒使用250个样本来记录这些信号。最后我获得了2500点。

我使用了Butterworth带通滤波器,其lowcut = 0.5,highcut = 15和order = 2。您可以在下面看到我的原始和过滤信号:

Top = Raw Photoplethysmogram signal, Bottom = Filtered Photoplethysmogram signal

我还尝试使用具有lowcut = 15和order = 2的Butterworth低通滤波器对此进行过滤。如您所见,我的原始信号和滤波后的信号如下:

Top = Raw Photoplethysmogram signal, Bottom = Filtered Photoplethysmogram signal

我在一些文章中读到0.5Hz和15Hz是此类信号的良好低切和高切频率。

在应用过滤器之前,我使用了Scipy Butterworth(来自scipy docs)算法来向我展示过滤器响应,效果很好。

在“开始”(开始时高程)之后,我过滤的信号似乎很好,但我不知道为什么开始。任何人都可以告诉我,在Butterworth过滤器中,“开始”是否正常?如果是,有什么方法可以解决?

感谢您的帮助。

我的代码:

RED, IR, nSamples, sRate = getAFESignal()

period = 1/sRate # Signal period.
# Desired cutoff frequency (in Hz) and filter order.
lowcut = 0.5
highcut = 15
orders = 2

plt.figure(1)

x = np.linspace(0, nSamples*period, nSamples, endpoint=True)

plt.subplot(2,1,1)
y = IR
plt.xlabel('Time (s)')
plt.ylabel('Voltage (V)')
plt.plot(x,y, label='Noisy signal')


plt.subplot(2,1,2)
yf = butter_bandpass_filter(IR, lowcut, highcut, nSamples, order=orders)
plt.xlabel('Time (s)')
plt.ylabel('Voltage (V)')
plt.plot(x, yf, label='Filtered signal')

plt.grid()
plt.show()

函数getAFEsignal()只是一个读取.txt文件并将其全部放入两个numpy数组的函数。

1 个答案:

答案 0 :(得分:1)

在图表中看到的初始瞬态是滤波器的阶跃响应,因为突然输入施加到处于静止状态的滤波器。如果您刚刚连接了包含此类带通滤波器的物理仪器,则该仪器的传感器可能已拾取输入数据样本,该样本从0(在探头断开连接时)跃升至第一个样本的〜0.126V。这样,仪器滤波器的响应就会显示出类似的瞬变。

但是,您可能对仪器的稳态响应更感兴趣,因为它不再受到这些外部因素(例如连接的探头)的干扰,并且有时间来适应信号的特性感兴趣。

实现此目的的一种方法是使用足够长的数据样本并丢弃初始瞬态。另一种方法是将滤波器的初始内部状态强制为接近在您的第一个输入采样之前的一段时间内施加了类似幅度的信号所期望的状态。例如,可以通过使用scipy.signal.lfilter_zi设置初始条件来完成此操作。

现在,我假设您使用过butter_bandpass_filter from SciPy Cookbook,它不会处理过滤器的初始条件。幸运的是,可以很容易地对此进行修改:

from scipy.signal import butter, lfilter, lfilter_zi

def butter_bandpass_filter_zi(data, lowcut, highcut, fs, order=5):
    b, a = butter_bandpass(lowcut, highcut, fs, order=order)
    zi = lfilter_zi(b, a)
    y,zo = lfilter(b, a, data, zi=zi*data[0])
    return y

enter image description here

这时要注意的另一件事是您将butter_bandpass_filter的调用方式为:

yf = butter_bandpass_filter(IR, lowcut, highcut, nSamples, order=orders)

传递nSamples(样本总数,在您的情况下为2500)作为第四个参数,而该函数期望的是采样率(在您的情况下为250)。这两个数量之间的系数为10,其效果等同于将滤波范围从[0.5,15] Hz减小到[0.05,1.5] Hz。要获得预期的带通频率范围,您应该将sRate作为第四个参数传递:

yf = butter_bandpass_filter_zi(IR, lowcut, highcut, sRate, order=orders)

enter image description here

最后,您可能会注意到最后一个输出的三角形比输入的三角形小。这是由于滤除了0.5Hz附近的一些低频成分引起的。如果那是您所期望的,那就太好了。否则,您仍然可以尝试使用截止频率来获得最佳效果。例如(我并不是说这是一个更好的频率范围),如果您设置lowcut=0.25,则会得到一个更三角形的图形,例如:

enter image description here