在 SciPy 中创建低通滤波器 - 理解方法和单元

Posted

技术标签:

【中文标题】在 SciPy 中创建低通滤波器 - 理解方法和单元【英文标题】:Creating lowpass filter in SciPy - understanding methods and units 【发布时间】:2014-10-01 05:34:30 【问题描述】:

我正在尝试使用 python 过滤嘈杂的心率信号。因为心率不应该高于每分钟 220 次,所以我想过滤掉所有高于 220 bpm 的噪音。我将 220/分钟转换为 3.66666666 赫兹,然后将该赫兹转换为 rad/s 以获得 23.0383461 rad/sec。

获取数据的芯片的采样频率是 30Hz,所以我将其转换为 rad/s 得到 188.495559 rad/s。

在网上查找了一些资料后,我发现了一些我想将其制成低通的带通滤波器的功能。 Here is the link the bandpass code,所以我把它改成了这样:

from scipy.signal import butter, lfilter
from scipy.signal import freqs

def butter_lowpass(cutOff, fs, order=5):
    nyq = 0.5 * fs
    normalCutoff = cutOff / nyq
    b, a = butter(order, normalCutoff, btype='low', analog = True)
    return b, a

def butter_lowpass_filter(data, cutOff, fs, order=4):
    b, a = butter_lowpass(cutOff, fs, order=order)
    y = lfilter(b, a, data)
    return y

cutOff = 23.1 #cutoff frequency in rad/s
fs = 188.495559 #sampling frequency in rad/s
order = 20 #order of filter

#print sticker_data.ps1_dxdt2

y = butter_lowpass_filter(data, cutOff, fs, order)
plt.plot(y)

我对此感到非常困惑,因为我很确定黄油函数会以 rad/s 为单位接收截止和采样频率,但我似乎得到了一个奇怪的输出。它实际上是赫兹吗?

其次,这两行的目的是什么:

    nyq = 0.5 * fs
    normalCutoff = cutOff / nyq

我知道这与归一化有关,但我认为奈奎斯特是采样频率的 2 倍,而不是一半。为什么要使用 nyquist 作为归一化器?

谁能解释一下如何使用这些功能创建过滤器?

我使用以下方法绘制了过滤器:

w, h = signal.freqs(b, a)
plt.plot(w, 20 * np.log10(abs(h)))
plt.xscale('log')
plt.title('Butterworth filter frequency response')
plt.xlabel('Frequency [radians / second]')
plt.ylabel('Amplitude [dB]')
plt.margins(0, 0.1)
plt.grid(which='both', axis='both')
plt.axvline(100, color='green') # cutoff frequency
plt.show()

并且得到了这个显然不会在 23 rad/s 时截止:

【问题讨论】:

【参考方案1】:

几个cmets:

Nyquist frequency 是采样率的一半。 您正在处理定期采样的数据,因此您需要一个数字滤波器,而不是模拟滤波器。这意味着您不应在对 butter 的调用中使用 analog=True,而应使用 scipy.signal.freqz(而不是 freqs)来生成频率响应。 这些简短实用函数的一个目标是允许您保留所有频率以 Hz 表示。您不必转换为弧度/秒。只要您使用一致的单位来表达频率,效用函数中的缩放就会为您处理标准化。

这是我修改后的脚本版本,后面是它生成的情节。

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


def butter_lowpass(cutoff, fs, order=5):
    nyq = 0.5 * fs
    normal_cutoff = cutoff / nyq
    b, a = butter(order, normal_cutoff, btype='low', analog=False)
    return b, a

def butter_lowpass_filter(data, cutoff, fs, order=5):
    b, a = butter_lowpass(cutoff, fs, order=order)
    y = lfilter(b, a, data)
    return y


# Filter requirements.
order = 6
fs = 30.0       # sample rate, Hz
cutoff = 3.667  # desired cutoff frequency of the filter, Hz

# Get the filter coefficients so we can check its frequency response.
b, a = butter_lowpass(cutoff, fs, order)

# Plot the frequency response.
w, h = freqz(b, a, worN=8000)
plt.subplot(2, 1, 1)
plt.plot(0.5*fs*w/np.pi, np.abs(h), 'b')
plt.plot(cutoff, 0.5*np.sqrt(2), 'ko')
plt.axvline(cutoff, color='k')
plt.xlim(0, 0.5*fs)
plt.title("Lowpass Filter Frequency Response")
plt.xlabel('Frequency [Hz]')
plt.grid()


# Demonstrate the use of the filter.
# First make some data to be filtered.
T = 5.0         # seconds
n = int(T * fs) # total number of samples
t = np.linspace(0, T, n, endpoint=False)
# "Noisy" data.  We want to recover the 1.2 Hz signal from this.
data = np.sin(1.2*2*np.pi*t) + 1.5*np.cos(9*2*np.pi*t) + 0.5*np.sin(12.0*2*np.pi*t)

# Filter the data, and plot both the original and filtered signals.
y = butter_lowpass_filter(data, cutoff, fs, order)

plt.subplot(2, 1, 2)
plt.plot(t, data, 'b-', label='data')
plt.plot(t, y, 'g-', linewidth=2, label='filtered data')
plt.xlabel('Time [sec]')
plt.grid()
plt.legend()

plt.subplots_adjust(hspace=0.35)
plt.show()

【讨论】:

是的,我确定。考虑“您需要以两倍带宽采样”的措辞;也就是说采样率必须是信号带宽的两倍。 换句话说:您以 30 Hz 的频率进行采样。这意味着您的信号带宽不应超过 15 Hz; 15 Hz 是奈奎斯特频率。 复活这个:我在另一个thread 中看到了使用 filtfilt 执行向后/向前过滤而不是 lfilter 的建议。您对此有何看法? @Bar:这些 cmets 不适合解决您的问题。您可以创建一个新的 *** 问题,但版主可能会关闭它,因为它不是 programming 问题。最好的地方大概是dsp.stackexchange.com @samjewell 这是一个随机数,我似乎总是与freqz 一起使用。我喜欢 平滑 绘图,具有足够的超高分辨率,我可以放大一点而无需重新生成绘图,并且在大多数情况下,8000 足够大。

以上是关于在 SciPy 中创建低通滤波器 - 理解方法和单元的主要内容,如果未能解决你的问题,请参考以下文章

Python图像处理使用低通滤波器模糊图像

《GCN 为什么是低通滤波器?具体在干啥?》

用matlab设计低通滤波器

android中有啥方法可以使用FFMPEG库过滤掉噪声(低通滤波器)。有人能帮我吗

RC低通滤波器

24基于原型的切比雪夫低通滤波器设计理论(插入损耗法)