01. 생체 신호 데이터(Bio-signal data)란?
생체 신호 데이터(Bio-signal data)는 인체에서 발생되는 신호를 측정하고 기록한 데이터로, 심전도(Electrocardiogram, ECG), 혈압(Blood Pressure, BP), 호흡(Relative Respiratory Rate, RRR), 뇌파(Electroencephalography, EEG) 등의 데이터를 의미한다. 이러한 생체 신호를 활용하면 우리의 신체 상태, 건강 상태, 감정 상태 등을 나타낼 수 있으며 최근에는 생체 신호를 수집하고 분석하는 다양한 기술과 알고리즘이 개발되어 건강 모니터링, 의료 진단, 생체 인증, 스포츠 및 운동 성능 개선을 위한 모니터링 등에 활용되고 있다.
02. 생체 신호 데이터 수집 방법 - PPG(photoplethysomography)
생체 신호 데이터를 수집하는 방법에는 여러가지가 있지만, 그중 PPG(Photoplethysmography)는 비침습적인 방법이며 사용이 간편다하는 장점이 있다. PPG는 일반적으로 손가락, 귀, 손목, 발목과 같이 피부가 얆은 부위에 LED(발광 다이오드)와 광학 센서를 적용하는데, 이때 빛이 혈액에서 흡수되는 정도를 측정하여 혈액의 산소 포화도와 맥박을 계산하는 방식이다. LED에서 발생된 빛은 피부를 통과하여 혈관에서 반사되며 일부는 혈액에서 흡수되는데, 이때 혈액은 산소를 운반하고 있기 때문에 산소 포화도와 혈액량이 증가하면 더 많은 빛을 흡수하게 된다. 이러한 원리로 PPG를 활용하여 혈압, 심박수, 혈중 산소 포화도 등을 측정할 수 있는 것이다.
03. 생체 신호 데이터 전처리
이렇게 수집된 생체 신호 데이터에 다음과 같은 방법으로 전처리를 수행한다.
(아래의 모든 기법을 다 적용해야하는것이 아니라 해당 데이터의 특성에 맞게 선택하여 처리한다.)
1) 필터링(FIitering)
2) 샘플링(Sampling)
3) 스케일링(Scaling)
4) 선형 보간(Linear interpolation)
5) 이상치 처리(Outlier Handling)
6) 특징 추출(Feature Extraction)
참고1) 주파수(Frequency) vs 파장(Wavelength)
주파수(Frequency)는 물체가 단위 시간당 진동하는 횟수를 의미하며 단위는 헤르츠(Hz)로 표현한다.
예를 들어 어떤 물체가 1초 동안 1번 진동하면 1Hz, 1초 동안 100번 진동할 경우 100Hz라고 표현한다.
파장(Wavelength)은 일정한 주기로 반복되는 파동의 길이를 의미한다(한 주기가 차지하는 거리를 나타냄).
따라서 파장의 길이가 짧을수록 파동이 빠르게 반복되고 높은 주파수를 가지는것을 의미하며, 반대로 파장의 길이가 길면 파동이 느리게 반복되고 낮은 주파수를 가지는 것이다.
다시 말해, 주파수는 시간의 개념으로 단위 시간당 반복되는 주기적인 변화의 수를 나타내며, 파장은 공간의 개념으로 한 주기가 차지하는 거리를 나타내는 것이다.
참고 2)저주파 vs 고주파
저주파란, 주파수가 낮은 신호를 의미하며 범위는 주어진 문제나 분석의 목적에 따라 다르게 정의될 수 있다. 저주파 신호는 우리가 알아보기 쉽고, 변화가 천천히 일어나기 때문에 생체 신호 분석에서 많이 사용되는데 주로 전체적인 추세나 대략적인 변화를 파악하는 데 사용된다.
고주파란, 주파수가 높은 신호를 의미한다. 예를 들어 심박수나 호흡 수 같이 빠르게 변화하는 생체 신호들은 고주파 신호에 해당된다. 또한 고주파 신호는 신호의 미세한 변화나 세부적인 특성을 파악하는 데 사용된다. 예를 들어 음향 신호의 경우, 고주파 성분은 음색이나 소리의 선명도와 같은 미세한 특성을 나타낸다.
3-1) 필터링(Filtering)
1️⃣ 저주파 필터링(Low-pass filtering)
저주파 필터링(low pass filtering)은 컷오프 주파수 이하의 주파수 성분만 통과시키고 컷오프 이상의 주파수 성분은 차단함으로써 신호의 저주파 성분은 보존하고 고주파 성분은 제거하는 필터링 기법이다(즉, 저주파 신호만 남기고 우리가 원하지 않는 잡음은 제거하는 것).
위의 그림에서 Original signal을 분해해 보면 여러 가지 주파수들이 섞여 Original signal이 형성되었음을 알 수 있다. 이처럼 여러 주파수가 합쳐져 있는 신호 데이터(Complex signal)에서 내가 원하는 대역의 주파수만 추출하고 싶은 경우 필터를 적용하는 것인데, 이때 저주파 만을 추출하고 싶다면 Original signal에 '저주파 필터링'을 적용하면 되는 것이다.
일반적으로 신호에서 저주파 성분은 신호의 전체적인 경향성과 추세를 나타내는 반면, 고주파 성분은 잡음과 같은 높은 주파수 변동을 의미한다. 따라서 신호 데이터에 저주파 필터링을 적용하면 노이즈(고주파)를 제거해 주어 신호를 부드럽게 만들어주는 효과가 있고, 이러한 방법을 통해 신호의 품질을 향상하고 원하는 정보를 추출할 수 있게 된다.
📁 저주파 필터링(low pass filtering)의 종류
생체 신호에서의 low pass filtering 시, 일반적으로 Butterworth filter와 Chebyshev filter 등이 사용된다.
📍버터워스 필터(Butterworth filter)
버터워스 필터(Butterworth filter)는 low pass filter의 한 종류로, 현재 성능이 가장 좋아 일반적으로 사용되는 필터이며
다음과 같은 식으로 나타낼 수 있다.
X(s) : input data (raw data)
Y(s) : output data (필터링된 데이터)
W cut_off : 차단 주파수(이 cut off 값 이상에 해당되는 주파수는 차단한다는 의미)
필터를 적용시킬 때에는
1) cut_off주파수를 증가시켜서 조정하는 방법과
2) 차수를 증가시켜서 조정하는 방법이 있다.
차수를 조정하면서 필터를 적용시키는 경우, 차수를 증가함에 따라 모양이 더 완만해지면서 경향성을 띄게 된다. 이때, phase 딜레이가 발생되며 차수를 한 개 올릴 때마다 90도씩 딜레이가 발생되는데 (1차는 90도-> 2차는 180도) 180도 이상 딜레이가 발생되면 안 되기 때문에 보통 2차 이상은 사용하지 않는다.(2차가 max)
📁python을 이용한 low pass filtering 적용
생체 신호 데이터에 low pass filtering을 적용하는 여러 가지 방법 중, scipy 라이브러리를 이용한 Butterworth low pass filter를 적용하는 코드를 정리하고자 한다.
#필요한 라이브러리 import
import numpy as np
from scipy import signal
from scipy.signal import butter, filtfilt
1. 먼저 low pass filtering에 필요한 라이브러리들을 import 한다.
#신호 데이터 생성
signal_data = np.random.randn(1000) #원본 신호 데이터
signal_data
2. np.random.randn함수를 사용하여 임의의 신호 데이터를 생성한다.
#필터링 적용을 위한 설정
order = 2 #필터의 차수
fs = 100 #샘플링 주파수
cutoff = 10 #저주파 컷오프 주파수
#저주파 필터링
nyq = 0.5 * fs #나이퀴스트 주파수
normal_cutoff = cutoff / nyq #정규화된 컷오프 주파수
b, a = signal.butter(order, normal_cutoff, btype ='low', analog=False) #필터 계수 생성
filtered_data = signal.lfilter(b, a, signal_data) #필터링 적용
3. 필터의 차수, 샘플링 주파수, 컷오프 주파수를 정의하고 저주파 필터링을 적용한다.
- order : 필터의 차수
- fs : 샘플링 주파수(기기가 1초에 몇 번 측정하는지 의미함)
- cutoff : 저주파 컷오프 주파수. 이때 cutoff frequency는 nyquiest주파수보다 작아야 한다는 제약조건이 있음
- nyq : nyquiest주파수로서, sampling frequency의 절반을 의미
〰️signal.butter( )
signal.butter함수는 scipy패키지의 signal 모듈에서 제공하는 Butterworth 필터계수를 생성하는 함수이며, Butterworth 필터는 저주파 또는 고주파 성분을 제거할때 사용한다.
* 입력 인수
b,a = signal.butter(N, Wn, btype ='low', analog = False, output = 'ba', fs = None)
- 'N' : 필터의 차수(정수)
- 'Wn' : 정규화된 컷오프 주파수(0~1 사이의 실수)
- 'btype' : 필터의 종류 (lowpass / highpass / bandpass / bandstop) 중 하나
- 'analog' : 아날로그 필터 여부 (True 또는 False)
- 'output' : 반환값 형태('ba' 또는 'zpk')
- 'fs' : 디지털 필터링인 경우 샘플링 주파수 (None 또는 양의 실수)
#결과 확인
import matplotlib.pyplot as plt
plt.plot(signal_data, 'b-', label='original')
plt.plot(filtered_data, 'r-', linewidth=2, label='filtered')
plt.legend(loc='best')
plt.show()
4. low pass filtering 된 결과를 확인한다.
🖇참고 문헌
https://www.youtube.com/watch?v=-P4fwQjX08Q
https://www.youtube.com/watch?v=JAdbMobYzO4&list=PLUwEe-QeX6th_7V6x7oQyxAiGbaS6HR5m&index=7