微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 scipy.signal 中制作低通滤波器?

如何解决如何在 scipy.signal 中制作低通滤波器?

我有几个关于在 python/scipy.signal 中制作低通滤波器的问题。希望得到任何答案。

  1. 我正在尝试了解 special format 的工作原理。它是否采用滤波器系数并将它们乘以数据值,以便对于 data[500],它会做
for b in range(0,len(coeff)):
    filtered = filtered + data[500-b]*coeff[b]

做那个和它正在做的有什么区别?

  1. 我也不明白点击次数在开始过滤时有何影响。对于不同的点击次数,我看到它从数据的不同值开始。我认为它只有在它具有必要的系数后才会开始。在我的示例中,我有来自 scipy.signal.firwin 的 683 个系数,但过滤器从 300-400 开始,正如您在图像 scipy.signal.lfilter 中看到的(过滤器为蓝色;正弦波为红色;x 从 0 开始-1000)
from scipy import signal

a = signal.firwin(683,cutoff = 1/30,window = "hamming")
t = signal.lfilter(a,1,sig)
  1. 如果 fs=1,cutoff = fs/30,我得到了一个带有 firwin 的低通滤波器,它被延迟了很多,如上图所示。我可以做些什么来改善延迟?

  2. 改变采样率会如何影响过滤器?

  3. 我在网上找到了两种估算点击次数方法

import math

(2/3) * math.log10(1/(10*ripple*attenuation)) * fs/transition_width
((-10*math.log10(ripple*attenuation) - 13)/(14.6)) * fs/transition_width

哪个是更好的近似值?

任何澄清将不胜感激。

解决方法

  1. 我正在尝试了解 scipy.signal.lfilter 的工作原理。

scipy.signal.lfilter(b,a,x) 实现了 "infinite impulse response" (IIR),aka "recursive",filtering,其中 ba 代表 IIR 滤波器,x 是输入信号。

b arg 是一个 M+1 分子(前馈)滤波器系数数组,而 a 是一个 N+1 分母(反馈)滤波器系数数组。按照惯例,a[0] = 1(否则可以将过滤器归一化以使其如此),因此我假设 a[0] = 1。第 n 个输出样本 y[n] 计算为

  y[n] = b[0] * x[n] + b[1] * x[n-1] + ... + b[M] * x[n-M]
                     - a[1] * y[n-1] - ... - a[N] * y[n-N].

IIR 过滤的特殊之处在于 y[n] 的这个公式取决于之前的 N 输出值 y[n-1],...,y[n-N];该公式是递归的。因此,为了开始这个过程,通常通过假设 y[n]x[n] 在 n scipy.signal.lfilter 在默认情况下所做的。>

您也可以使用 scipy.signal.lfilter 通过设置 a = [1] 来应用“有限脉冲响应”(FIR),正如您在问题 2 中所做的那样。然后过滤公式中没有递归反馈项,所以过滤就变成了 bx 的简单卷积。

  1. 我也不明白点击次数在开始过滤时有何影响。对于不同的点击次数,我看到它从数据的不同值开始。我认为它只有在它具有必要的系数后才会开始。在我的示例中,我有 683 个来自 scipy.signal.firwin 的系数,但滤波器从 300-400 开始,正如您在图像中看到的 Firwin 低通滤波器(滤波器为蓝色;正弦波为红色;x 从 0-1000 )

scipy.signal.lfilter 立即开始过滤。正如我上面提到的,它这样做(默认情况下)假设 y[n]x[n] 对于 n y[0] 计算为>

  y[0] = b[0] * x[0].

但是,根据您的过滤器,b[0] 可能接近于零,这可以解释为什么一开始似乎什么也没有发生。

检查滤波器行为的一个好方法是计算其“脉冲响应”,即查看通过将单位脉冲 [1,...] 作为输入传递而产生的输出:

plot(scipy.signal.lfilter(b,[1] + [0] * 800))

这是b = firwin(683,cutoff = 1/30,window = "hamming")a = [1] 我得到的结果:

Impulse response

从该图中我们可以看到几件事:脉冲响应起初非常小,然后上升并振荡,在样本索引 341 处达到峰值,然后再次对称衰减为零。滤波器的延迟为 341 = 683 // 2,即您在设计滤波器时指定给 firwin 的抽头数的一半。

  1. 我可以做些什么来改善延迟?

尝试将抽头数量 683 减少到更小。或者,如果您不需要过滤为 causal,请尝试 scipy.ndimage.convolve1d,它会移动计算以便过滤器居中:

scipy.ndimage.convolve1d(sig,firwin_filter,mode='constant')
  1. 改变采样率会如何影响过滤器?

对于大多数滤波器设计,如果截止频率小于采样率的 1/4,那么精确的采样率几乎没有影响。或者换句话说,除非截止频率适度接近奈奎斯特频率,否则这通常不是问题。

  1. 我在网上找到了两种估算点击次数的方法。

我不熟悉这些公式。请注意,实现目标特性所需的抽头数量取决于特定的设计方法,因此请注意这些公式假设的上下文。

scipy.signal 内,我建议将 kaiserordfirwinfirwin2 一起用于目标波纹量和过渡宽度。 Here is their example,其中 65 是以 dB 为单位的阻带纹波,width 是以 Hz 为单位的过渡宽度:

使用 kaiserord 确定过滤器的长度和 Kaiser 窗口的参数。

>>> numtaps,beta = kaiserord(65,width/(0.5*fs))
>>> numtaps
167
>>> beta
6.20426

使用 firwin 创建 FIR 滤波器。

>>> taps = firwin(numtaps,cutoff,window=('kaiser',beta),scale=False,nyq=0.5*fs)

编辑:对于其他设计,kaiserord 可能会进入正确的范围,但不要依赖于实现波纹或过渡宽度的目标量。所以一个可能的通用策略可能是一个像这样的迭代过程:

  1. 使用 kaiserord 获得点按次数的初始估计值。
  2. 用那么多的水龙头设计过滤器。
  3. 使用 scipy.signal.freqz 获取滤波器的频率响应。
  4. 评估响应幅度与所需响应的接近程度。即,在通带上,从 1 计算最大绝对差,在阻带上,从 0 计算最大绝对差。
  5. 如果响应不够接近,请增加敲击次数并返回到第 2 步。否则,看看是否可以通过减少敲击次数来摆脱困境。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。