web-dev-qa-db-ja.com

Pythonハイパスフィルター

このコードを使用して、pythonにハイパスフィルターを実装しました。

from scipy.signal import butter, filtfilt
import numpy as np

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

def butter_highpass_filter(data, cutoff, fs, order=5):
    b, a = butter_highpass(cutoff, fs, order=order)
    y = filtfilt(b, a, data)
    return y

rawdata = np.loadtxt('sampleSignal.txt', skiprows=0)
signal = rawdata
fs = 100000.0

cutoff = 100
order = 6
conditioned_signal = butter_highpass_filter(signal, cutoff, fs, order)

このフィルターを100 kHzの電圧信号に適用していますが、60 Hz以上のカットオフ周波数で正常に機能します。ただし、以下では機能しません。 10 Hz以下のすべての周波数を遮断したいと思います。私の間違いはどこにあるのでしょうか?私が観察したのは、フィルターの次数が低いほどカットオフ周波数が低くなる可能性があることです。

サンプル信号はここにあります。

7
ChrisG

これがあなたのお役に立てば幸いです。

import numpy as np
import pandas as pd
from scipy import signal
import matplotlib.pyplot as plt
def sine_generator(fs, sinefreq, duration):
    T = duration
    nsamples = fs * T
    w = 2. * np.pi * sinefreq
    t_sine = np.linspace(0, T, nsamples, endpoint=False)
    y_sine = np.sin(w * t_sine)
    result = pd.DataFrame({ 
        'data' : y_sine} ,index=t_sine)
    return result

def butter_highpass(cutoff, fs, order=5):
    nyq = 0.5 * fs
    normal_cutoff = cutoff / nyq
    b, a = signal.butter(order, normal_cutoff, btype='high', analog=False)
    return b, a

def butter_highpass_filter(data, cutoff, fs, order=5):
    b, a = butter_highpass(cutoff, fs, order=order)
    y = signal.filtfilt(b, a, data)
    return y

fps = 30
sine_fq = 10 #Hz
duration = 10 #seconds
sine_5Hz = sine_generator(fps,sine_fq,duration)
sine_fq = 1 #Hz
duration = 10 #seconds
sine_1Hz = sine_generator(fps,sine_fq,duration)

sine = sine_5Hz + sine_1Hz

filtered_sine = butter_highpass_filter(sine.data,10,fps)

plt.figure(figsize=(20,10))
plt.subplot(211)
plt.plot(range(len(sine)),sine)
plt.title('generated signal')
plt.subplot(212)
plt.plot(range(len(filtered_sine)),filtered_sine)
plt.title('filtered signal')
plt.show()
14

私の評判は低いので、「カットオフとフィルター次数の関係は何ですか?」という質問にコメントすることはできません。これは元の質問に対する答えではありません。

FIRフィルターの場合、所定のカットオフ周波数に対して、インパルス応答プロットの勾配(| H(f)| vs f)は、高次フィルターの場合に急勾配になります。そのため、望ましくない周波数範囲でより高い減衰を実現するには、フィルター次数を増やします。しかし、フィルターの次数が非常に高く、インパルス応答が理想的なボックス関数である場合はどうなりますか?効果のようなシンボル間干渉(デジタル通信のISI)が表示されます。この効果の強さは、カットオフ周波数とサンプリング周波数の比が小さくなると増加します(周波数領域でのボックス関数の幅とsinc関数のメインローブの幅の関係を考えてください)。

TI DSPマイクロコントローラーに非常に狭い帯域のローパスIIRフィルターを実装しようとしたときに最初にこれを観察しました。 TIライブラリは、よく知られた切り捨て効果を処理するために、カスケードされたバイカッド構造としてフィルタを実装しました。問題は切り捨てのみによるものではないため、これでも問題を解決できませんでした。この問題を解決する方法は、アンチエイリアシングフィルターを使用し、続いて入力信号をダウンサンプリングし、次に希望するローパスIIRフィルターを使用することでした。

周波数領域に変換されたLPFであるHPFを実装していることを理解しています。これがあなたの質問のいくつかに答えることを願っています。ダウンサンプリングが有効かどうか教えてください。

4

上記の検証関数を追加します Konstantin Purtov のコードなので、順序とカットオフ周波数の関係を確認できます。コードの大部分は Warren Weckesser からのものです。

import scipy
import sys  
from scipy import signal
from scipy import pi
from scipy.io.wavfile import write
import matplotlib.pyplot as plt
import numpy as np    
from scipy.signal import butter, lfilter, freqz   


# ----- ----- ----- -----    
def butter_highpass(cutoff, fs, order=5):
    nyq = 0.5 * fs
    normal_cutoff = cutoff / nyq
    b, a = signal.butter(order, normal_cutoff, btype='high', analog=False)
    return b, a

def butter_highpass_filter(data, cutoff, fs, order=5):
    b, a = butter_highpass(cutoff, fs, order=order)
    y = signal.filtfilt(b, a, data)
    return y


# ----- -----    
# (1)
def foo(sel):
    if (sel == 1):
        # Filter requirements.
        order = 6
        fs = 300.0  # sample rate, Hz
        cutoff = 10  # desired cutoff frequency of the filter, Hz

        # Get the filter coefficients so we can check its frequency response.
        b, a = butter_highpass(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("High Filter Frequency Response")
        plt.xlabel('Frequency [Hz]')
        plt.grid()

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

        # Filter the data, and plot both the original and filtered signals.
        y = butter_highpass_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()
    else:
        print ('Please, choose among choices, thanks.')


# ----- -----
def main():
    sel = int (sys.argv[1])
    foo(sel)


# ----- ----- ----- ----- ----- -----
if __name__ == '__main__':
    main()
0
Cloud Cho