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

Python 如何在scipy.signal中制作低通滤波器?,python,scipy,signal-processing,lowpass-filter,Python,Scipy,Signal Processing,Lowpass Filter,关于在python/scipy.signal中制作低通滤波器,我有几个问题。如有任何答案,我将不胜感激 我在试着理解它是如何工作的。它是否将滤波器系数与数据值相乘,这样对于数据[500],就可以了 这样做和它正在做的有什么区别 我也不明白当它开始过滤时,抽头的数量是如何影响的。对于不同的抽头数,我看到它从数据上的不同值开始。我假设它只有在有了必要的系数后才会开始。在我的示例中,我有683个来自scipy.signal.firwin的系数,但滤波器从300-400开始,正如您在图像中看到的那样(滤

关于在python/scipy.signal中制作低通滤波器,我有几个问题。如有任何答案,我将不胜感激

  • 我在试着理解它是如何工作的。它是否将滤波器系数与数据值相乘,这样对于
    数据[500]
    ,就可以了
  • 这样做和它正在做的有什么区别

  • 我也不明白当它开始过滤时,抽头的数量是如何影响的。对于不同的抽头数,我看到它从数据上的不同值开始。我假设它只有在有了必要的系数后才会开始。在我的示例中,我有683个来自
    scipy.signal.firwin
    的系数,但滤波器从300-400开始,正如您在图像中看到的那样(滤波器为蓝色;正弦波为红色;x为0-1000)
  • 当fs=1,cutoff=fs/30时,我得到了一个带有firwin的低通滤波器,它延迟了很多,如上图所示。我能做些什么来改善延迟

  • 更改采样率将如何影响过滤器

  • 我在网上找到了两种近似抽头数的方法:

  • 哪一个是更好的近似值

    如有任何澄清,将不胜感激

  • 我在试着理解它是如何工作的
  • scipy.signal.lfilter(b,a,x)
    实现,其中
    b
    a
    表示IIR滤波器,
    x
    是输入信号

    b
    arg是
    M+1
    分子(前馈)滤波器系数的数组,
    a
    N+1
    分母(反馈)滤波器系数的数组。按照惯例,
    a[0]
    =1(否则可以对过滤器进行规范化,使其成为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]
    ;这个公式是递归的。因此,为了开始这个过程,通常通过假设
    y[n]
    x[n]
    对于n<0为零,将过滤器“初始化为零”。默认情况下,
    scipy.signal.lfilter
    就是这样做的

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

  • 我也不明白当它开始过滤时,抽头的数量是如何影响的。对于不同的抽头数,我看到它从数据上的不同值开始。我假设它只有在有了必要的系数后才会开始。在我的示例中,我从scipy.signal.firwin中得到683个系数,但滤波器从300-400开始,正如您在图像firwin低通滤波器中看到的那样(滤波器为蓝色;正弦波为红色;x为0-1000)
  • scipy.signal.lfilter
    立即开始过滤。正如我上面提到的,它这样做(默认情况下)假设
    y[n]
    x[n]
    在n<0时为零,这意味着它计算的第一个输出样本是
    y[0]
    ,计算如下

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

    检查过滤器性能的一个好方法是计算其“脉冲响应”,即查看通过单位脉冲
    [1,0,0,…]
    作为输入产生的输出:

    plot(scipy.signal.lfilter(b, a, [1] + [0] * 800))
    
    下面是我从
    b=firwin(683,cutoff=1/30,window=“hamming”)
    a=[1]

    从这幅图中我们可以看到一些东西:脉冲响应起初非常小,然后上升和振荡,峰值在样本指数341,然后对称衰减到零。过滤器的延迟为341=683//2,即设计过滤器时指定给
    firwin
    的抽头数的一半

  • 我能做些什么来改善延迟
  • 尝试将轻敲683的数量减少到更小的数量。或者,如果您不需要过滤,请尝试,这样可以移动计算,使过滤器居中:

    scipy.ndimage.convolve1d(sig, firwin_filter, mode='constant')
    
  • 更改采样率将如何影响过滤器
  • 对于大多数滤波器设计,如果截止值小于采样率的1/4,则准确的采样率几乎没有影响。或者换句话说,这通常不是问题,除非截止值适度接近奈奎斯特频率

  • 我在网上找到了两种方法来估计水龙头的数量
  • 我不熟悉这些公式。请注意,实现目标特性所需的抽头数取决于特定的设计方法,因此请注意这些公式假设的上下文

    scipy.signal
    中,我建议将
    kaiserord
    firwin
    firwin2
    一起使用,以获得波纹量和过渡宽度的目标值,其中65是以dB为单位的阻带纹波,
    宽度
    是以Hz为单位的过渡宽度:

    用于确定过滤器的长度和Kaiser窗口的参数

    >>> numtaps, beta = kaiserord(65, width/(0.5*fs))
    >>> numtaps
    167
    >>> beta
    6.20426
    
    用于创建FIR滤波器

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

    编辑:对于其他设计,
    kaiserord
    可能会达到正确的标准,但不必依赖于这一标准来实现目标波纹量或过渡宽度。因此,一个可能的总体策略可能是这样一个迭代过程:

  • 使用
    kaiserord
    获得抽头数量的初始估计值
  • 设计具有如此多抽头的滤波器
  • 用于获取过滤器的频率
    scipy.ndimage.convolve1d(sig, firwin_filter, mode='constant')
    
    >>> numtaps, beta = kaiserord(65, width/(0.5*fs))
    >>> numtaps
    167
    >>> beta
    6.20426
    
    >>> taps = firwin(numtaps, cutoff, window=('kaiser', beta),
                      scale=False, nyq=0.5*fs)