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 |