簡體   English   中英

如何使用Scipy.signal.butter實現帶通Butterworth濾波器

[英]How to implement band-pass Butterworth filter with Scipy.signal.butter

更新:

我找到了一個基於這個問題的Scipy Recipe! 所以,對於任何有興趣的人,請直接進入: 目錄»信號處理»Butterworth Bandpass


我很難實現最初為一維numpy陣列(時間序列)實現Butterworth帶通濾波器的簡單任務。

我必須包括的參數是sample_rate,截止頻率IN HERTZ和可能的順序(其他參數,如衰減,固有頻率等對我來說更加模糊,因此任何“默認”值都可以)。

我現在擁有的是這個,它似乎是一個高通濾波器,但我不確定我是否做得對:

def butter_highpass(interval, sampling_rate, cutoff, order=5):
    nyq = sampling_rate * 0.5

    stopfreq = float(cutoff)
    cornerfreq = 0.4 * stopfreq  # (?)

    ws = cornerfreq/nyq
    wp = stopfreq/nyq

    # for bandpass:
    # wp = [0.2, 0.5], ws = [0.1, 0.6]

    N, wn = scipy.signal.buttord(wp, ws, 3, 16)   # (?)

    # for hardcoded order:
    # N = order

    b, a = scipy.signal.butter(N, wn, btype='high')   # should 'high' be here for bandpass?
    sf = scipy.signal.lfilter(b, a, interval)
    return sf

在此輸入圖像描述

文檔和示例令人困惑和模糊,但我希望實現標記為“for bandpass”的表述中的表單。 評論中的問號顯示我只是在不了解正在發生的事情的情況下復制粘貼了一些示例。

我不是電氣工程師或科學家,只是需要對EMG信號執行一些相當直接的帶通濾波的醫療設備設計師。

您可以跳過使用buttord,而只需選擇過濾器的訂單,看看它是否符合您的過濾條件。 要為帶通濾波器生成濾波器系數,請給出butter()濾波器階數,截止頻率Wn=[low, high] (表示為奈奎斯特頻率的分數,即采樣頻率的一半)和波段類型btype="band"

這是一個腳本,它定義了一些用於處理Butterworth帶通濾波器的便利功能。 當作為腳本運行時,它會生成兩個圖。 一個顯示了相同采樣率和截止頻率的幾個濾波器階數的頻率響應。 另一個圖顯示了濾波器(order = 6)對采樣時間序列的影響。

from scipy.signal import butter, lfilter


def butter_bandpass(lowcut, highcut, fs, order=5):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = butter(order, [low, high], btype='band')
    return b, a


def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
    b, a = butter_bandpass(lowcut, highcut, fs, order=order)
    y = lfilter(b, a, data)
    return y


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 = 5000.0
    lowcut = 500.0
    highcut = 1250.0

    # Plot the frequency response for a few different orders.
    plt.figure(1)
    plt.clf()
    for order in [3, 6, 9]:
        b, a = butter_bandpass(lowcut, highcut, fs, order=order)
        w, h = freqz(b, a, worN=2000)
        plt.plot((fs * 0.5 / np.pi) * w, abs(h), label="order = %d" % order)

    plt.plot([0, 0.5 * fs], [np.sqrt(0.5), np.sqrt(0.5)],
             '--', label='sqrt(0.5)')
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Gain')
    plt.grid(True)
    plt.legend(loc='best')

    # Filter a noisy signal.
    T = 0.05
    nsamples = T * fs
    t = np.linspace(0, T, nsamples, endpoint=False)
    a = 0.02
    f0 = 600.0
    x = 0.1 * np.sin(2 * np.pi * 1.2 * np.sqrt(t))
    x += 0.01 * np.cos(2 * np.pi * 312 * t + 0.1)
    x += a * np.cos(2 * np.pi * f0 * t + .11)
    x += 0.03 * np.cos(2 * np.pi * 2000 * t)
    plt.figure(2)
    plt.clf()
    plt.plot(t, x, label='Noisy signal')

    y = butter_bandpass_filter(x, lowcut, highcut, fs, order=6)
    plt.plot(t, y, label='Filtered signal (%g Hz)' % f0)
    plt.xlabel('time (seconds)')
    plt.hlines([-a, a], 0, T, linestyles='--')
    plt.grid(True)
    plt.axis('tight')
    plt.legend(loc='upper left')

    plt.show()

以下是此腳本生成的圖:

多個過濾器訂單的頻率響應

在此輸入圖像描述

接受的答案中的過濾器設計方法是正確的,但它有一個缺陷。 使用b,a設計的SciPy帶通濾波器不穩定 ,可能會在更高的濾波器階數下導致錯誤的濾波器

相反,使用濾波器設計的sos(二階部分)輸出。

from scipy.signal import butter, sosfilt, sosfreqz

def butter_bandpass(lowcut, highcut, fs, order=5):
        nyq = 0.5 * fs
        low = lowcut / nyq
        high = highcut / nyq
        sos = butter(order, [low, high], analog=False, btype='band', output='sos')
        return sos

def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
        sos = butter_bandpass(lowcut, highcut, fs, order=order)
        y = sosfilt(sos, data)
        return y

此外,您可以通過更改來繪制頻率響應

b, a = butter_bandpass(lowcut, highcut, fs, order=order)
w, h = freqz(b, a, worN=2000)

sos = butter_bandpass(lowcut, highcut, fs, order=order)
w, h = sosfreqz(sos, worN=2000)

對於帶通濾波器,ws是包含下角和上角頻率的元組。 這些代表數字頻率,濾波器響應比通帶小3 dB。

wp是一個包含阻帶數字頻率的元組。 它們代表最大衰減開始的位置。

gpass是通帶中以dB為單位的最大值,而gstop是阻帶中的值。

比如說,您想設計一個濾波器,采樣率為8000個樣本/秒,轉角頻率為300和3100 Hz。 奈奎斯特頻率是采樣率除以2,或者在本例中為4000 Hz。 等效數字頻率為1.0。 兩個轉角頻率則為300/4000和3100/4000。

現在假設您希望阻帶從轉角頻率下降30 dB +/- 100 Hz。 因此,您的阻帶將從200和3200 Hz開始,導致數字頻率為200/4000和3200/4000。

要創建過濾器,您可以將按鈕稱為

fs = 8000.0
fso2 = fs/2
N,wn = scipy.signal.buttord(ws=[300/fso2,3100/fso2], wp=[200/fs02,3200/fs02],
   gpass=0.0, gstop=30.0)

所得濾波器的長度取決於阻帶的深度和響應曲線的陡度,響應曲線的陡度由轉角頻率和阻帶頻率之間的差值確定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM