본문으로 바로가기

Scipy에서 제공하는 butterworth 필터(주파수 필터)를 사용해

      BPF(bandpass), LPF(low), HPF(high)를 구하는 방법에 대해 기술했다.

 

 

z 신호 (50Hz, 20Hz를 합성)

#-*- coding:utf-8 -*-
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline

Fs = 2000.
Ts = 1 / Fs
te = 1.0
t = np.arange(0.0, te, Ts)

# Signal x (20Hz) + Signal y (50Hz)
x = np.cos(2 * np.pi * 20 * t)
y = np.cos(2 * np.pi * 50 * t)

# Signal z
z = x + y

N = len(z)

k = np.arange(N)
T = N / Fs
freq = k / T
freq = freq[range(int(N/2))]

# FFT 적용
yfft = np.fft.fft(z)
yf = yfft / N
yf = yf[range(int(N/2))]

plt.rcParams["figure.figsize"] = (15,4)

# FFT 출력
plt.plot(freq, abs(yf), 'b')
plt.xlabel('Frequency')

plt.ylabel('Amplitude')
plt.xlim(0, Fs / 20)
plt.show()

 

 

Bandpass filter, 일부 주파수 대역 범위만 추출할 수 있는 필터 (통과 대역)

해당 코드에서는 40 ~ 100 Hz의 주파수 대역만 통과 시키도록 했다.

> order: order계수가 클수록 이상적인 필터, 어느정도로 급격하게 자를 것인가 (하이퍼파라미터 튜닝 느낌)

from scipy.signal import butter

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


# BPF setting ( 나머지 주파수는 자르고 40 ~ 100 hz 만 추출하겠다.)
lowcut = 40.0
highcut = 100.0
    
# BPF
yy = butter_bandpass_filter(z, lowcut, highcut, Fs, order=5)

# 1. 원 신호 Plot
plt.plot(t, z, 'y', label='origin')

# 2. 필터 적용된 Plot
plt.plot(t, yy, 'b', label='filtered data')
plt.legend()
plt.show() 
    
# 3. 필터 적용된 FFT Plot
yf = np.fft.fft(yy) / N
yf = yf[range(int(N/2))]

plt.title("BPF")
plt.plot(freq, abs(yf), 'k')
plt.xlim(0, Fs / 20)
plt.show()

 

20Hz에 해당하는 주파수가 사라진 것을 확인할 수 있다.

 

 

Low pass filter, 선택한 차단 주파수(cutoff Frequency) 보다 낮은 주파수만 통과시키는 필터 (저역 패스 필터)

30Hz 보다 낮은 주파수만 통과시킨다. (0~30Hz만 그려짐)

def butter_lowpass(cutoff, fs, order=9):
    nyq = 0.5 * fs
    normal_cutoff = cutoff / nyq
    b, a = butter(order, normal_cutoff, btype='low', analog=False)
    return b, a

def butter_lowpass_filter(data, cutoff, fs, order=9):
    b, a = butter_lowpass(cutoff, fs, order=order)
    y = lfilter(b, a, data)
    return y

# LPF
cutoff = 30.

lpf = butter_lowpass_filter(z, cutoff, Fs, order=9)

# 1. 원 신호
plt.plot(t, z, 'y', label='origin')
# 2. 필터 적용된 Plot
plt.plot(t, lpf, 'b', label='filtered data')
plt.legend()
plt.show() 

# 3. 필터 적용된 FFT Plot
yfft = np.fft.fft(lpf)
yf = yfft / N
yf = yf[range(int(N/2))]

plt.plot(freq, abs(yf), 'm')
plt.title("LBP")
plt.xlim(0, Fs / 20)
plt.show()

50Hz에 해당하는 주파수가 사라진 것을 확인할 수 있다.

 

 

High pass filter, 선택한 차단 주파수(cutoff Frequency) 보다 높은 주파수만 통과시키는 필터 (고역 패스 필터)

50Hz보다 높은 주파수만 통과시킨다.

from scipy import signal

def butter_highpass(cutoff, fs, order=3):
    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=3):
    b, a = butter_highpass(cutoff, fs, order=order)
    y = signal.filtfilt(b, a, data)
    return y


# HPF
cutoff = 50.
hpf = butter_highpass_filter(z, cutoff, Fs)

# 1. 원 신호
plt.plot(t, z, 'y', label='origin')

# 2. 필터 적용된 Plot
plt.plot(t, hpf, 'b', label='filtered data')
plt.legend()
plt.show() 

# 3. 필터 적용된 FFT Plot
yfft = np.fft.fft(hpf)
yf = yfft / N
yf = yf[range(int(N/2))]

plt.plot(freq, abs(yf), 'b')
plt.title("HBF")
plt.xlim(0, Fs / 20)
plt.show()

20Hz에 해당하는 주파수가 사라진 것을 확인할 수 있다.

 

'Domain > Audio' 카테고리의 다른 글

# Spectrogram_python  (0) 2020.09.16
# FFT_python  (0) 2020.07.05