【问题标题】:Bandpass filter in pythonpython中的带通滤波器
【发布时间】:2013-04-24 11:20:10
【问题描述】:

我正在尝试在 python 中获得一个具有 128 点汉明窗的带通滤波器,截止频率为 0.7-4Hz。我从图像中获取我的信号样本。 (1 个样本 = 1 个图像)。 fps经常变化。

如何在 python 中做到这一点?我读到这个:http://mpastell.com/2010/01/18/fir-with-scipy/ 但我发现 firwin 相当混乱。如何使用这个变量 fps 来做到这一点?

【问题讨论】:

  • 您的采样率是多少?如果不知道这一点,您将无法指定数字截止频率。
  • 好吧,既然它等于每秒的帧数,就是这样。它不断变化...范围从 20 fps 到 60 fps ...因此采样频率会发生变化。
  • 你是说你试图过滤的数据不是以统一的速率采样的吗?如果是这种情况,您将无法使用 FIR 滤波器或任何其他数字滤波器。它们需要统一、一致的采样率。
  • 好吧,它大约是 63 fps,所以 ...63 hz

标签: python scipy signal-processing


【解决方案1】:

另一种选择是(异步)采样率转换,以在过滤之前将数据转换为恒定采样率(如“网格化”)。当然,这仅在您知道采样率的情况下才有效,并且仅在您确实需要过滤数据(而不仅仅是估计频谱)时才有用。

为此,例如scipy.interpolate 中的 InterpolatedUnivariateSpline 可以逐帧应用,速度相当快。

【讨论】:

    【解决方案2】:

    您可以使用函数scipy.signal.firwin 或scipy.signal.firwin2 创建带通 FIR 滤波器。你也可以使用scipy.signal.remez设计一个FIR滤波器

    以下代码提供了一些用于创建带通 FIR 滤波器的便利包装器。它使用这些来创建与问题中请求的数字相对应的带通滤波器。这假设采样是均匀进行的。如果采样不均匀,则不适合使用 FIR 滤波器。

    from scipy.signal import firwin, remez, kaiser_atten, kaiser_beta
    
    # Several flavors of bandpass FIR filters.
    
    def bandpass_firwin(ntaps, lowcut, highcut, fs, window='hamming'):
        nyq = 0.5 * fs
        taps = firwin(ntaps, [lowcut, highcut], nyq=nyq, pass_zero=False,
                      window=window, scale=False)
        return taps
    
    def bandpass_kaiser(ntaps, lowcut, highcut, fs, width):
        nyq = 0.5 * fs
        atten = kaiser_atten(ntaps, width / nyq)
        beta = kaiser_beta(atten)
        taps = firwin(ntaps, [lowcut, highcut], nyq=nyq, pass_zero=False,
                      window=('kaiser', beta), scale=False)
        return taps
    
    def bandpass_remez(ntaps, lowcut, highcut, fs, width):
        delta = 0.5 * width
        edges = [0, lowcut - delta, lowcut + delta,
                 highcut - delta, highcut + delta, 0.5*fs]
        taps = remez(ntaps, edges, [0, 1, 0], Hz=fs)
        return taps
    
    
    if __name__ == "__main__":
        import numpy as np
        import matplotlib.pyplot as plt
        from scipy.signal import freqz
    
        # Sample rate and desired cutoff frequencies (in Hz).
        fs = 63.0
        lowcut = 0.7
        highcut = 4.0
    
        ntaps = 128
        taps_hamming = bandpass_firwin(ntaps, lowcut, highcut, fs=fs)
        taps_kaiser16 = bandpass_kaiser(ntaps, lowcut, highcut, fs=fs, width=1.6)
        taps_kaiser10 = bandpass_kaiser(ntaps, lowcut, highcut, fs=fs, width=1.0)
        remez_width = 1.0
        taps_remez = bandpass_remez(ntaps, lowcut, highcut, fs=fs,
                                    width=remez_width)
    
        # Plot the frequency responses of the filters.
        plt.figure(1, figsize=(12, 9))
        plt.clf()
    
        # First plot the desired ideal response as a green(ish) rectangle.
        rect = plt.Rectangle((lowcut, 0), highcut - lowcut, 1.0,
                             facecolor="#60ff60", alpha=0.2)
        plt.gca().add_patch(rect)
    
        # Plot the frequency response of each filter.
        w, h = freqz(taps_hamming, 1, worN=2000)
        plt.plot((fs * 0.5 / np.pi) * w, abs(h), label="Hamming window")
    
        w, h = freqz(taps_kaiser16, 1, worN=2000)
        plt.plot((fs * 0.5 / np.pi) * w, abs(h), label="Kaiser window, width=1.6")
    
        w, h = freqz(taps_kaiser10, 1, worN=2000)
        plt.plot((fs * 0.5 / np.pi) * w, abs(h), label="Kaiser window, width=1.0")
    
        w, h = freqz(taps_remez, 1, worN=2000)
        plt.plot((fs * 0.5 / np.pi) * w, abs(h),
                 label="Remez algorithm, width=%.1f" % remez_width)
    
        plt.xlim(0, 8.0)
        plt.ylim(0, 1.1)
        plt.grid(True)
        plt.legend()
        plt.xlabel('Frequency (Hz)')
        plt.ylabel('Gain')
        plt.title('Frequency response of several FIR filters, %d taps' % ntaps)
    
        plt.show()
    

    这是脚本生成的情节。当然,在本地运行脚本会更有用,这样你可以放大细节。

    【讨论】:

      【解决方案3】:

      尝试过滤采样率不一致的数据非常困难(不可能?)。所以你要做的是:

      1. 创建一个具有固定采样率的新信号。固定采样率应为最大采样率或更高。通过设置一个新的“网格”来表示新样本应该去哪里,并从现有数据中插入它们的值来做到这一点。根据您需要的准确度,存在多种插值方法。线性插值可能不是一个糟糕的起点,但这取决于您在做什么。如果您不确定,请联系https://dsp.stackexchange.com/。

      2. 完成此操作后,您可以对信号应用标准信号处理方法,因为样本是均匀放置的,例如您链接的帖子中描述的那些。

      3. 如有必要,您可能需要再次插值以恢复原始样本位置。

      如果您只想分析您的数据,您可能会对Lomb Periodigram 感兴趣。您可以使用 Lomb Periodigram,然后只查看相关频率,或者根据需要对结果进行加权,而不是对您的数据进行带通分析。 (另见数值配方系列。第 13.8 章称为“不均匀间隔数据的光谱分析”,这似乎比维基百科页面更友好的介绍)

      ​​>

      【讨论】:

      • 仅供参考:SciPy 有一个 Lomb-Scargle 周期图的实现,scipy.signal.lombscargle。
      猜你喜欢
      • 2013-10-07
      • 2016-09-10
      • 1970-01-01
      • 2015-11-04
      • 2023-04-10
      • 2015-03-05
      • 2019-04-09
      • 2017-01-05
      • 1970-01-01
      相关资源
      最近更新 更多