신호 필터처리

In [2]:
import numpy as np
import matplotlib.pyplot as plt
from signal_processor import SignalProcessor

# 시간 배열 생성: 0부터 5 + 0.01 까지 0.01 간격으로 생성 (총 501개 데이터 포인트)
time = np.arange(0, 5 + 0.01, 0.01)

# 노이즈 생성: 평균 0, 표준편차 0.5인 정규분포를 따르는 랜덤 노이즈
# time.shape와 동일한 크기로 생성하여 신호와 더할 수 있도록 함
noise = np.random.normal(0, 0.5, size=time.shape)

# 신호 생성: 사인파에 노이즈를 더한 합성 신호
# np.sin(time)은 순수한 사인파 신호, noise를 더해서 실제 측정된 것처럼 노이즈가 포함된 신호를 만듦
signal = np.sin(time) + noise

moving average, low-pass 필터를 적용하고 원본과 비교해본다

In [3]:
sp = SignalProcessor(window_size=5, alpha=0.1)

# moving average 필터를 위한 리스트
ma_output = []
# low-pass 필터를 위한 리스트
lp_output = []

for val in signal:
    ma_output.append(sp.moving_average(val))
    lp_output.append(sp.low_pass_filter(val))

sp.plot_signals(time, signal, ma_output, lp_output)
Notebook output

확대해서 각각의 차이를 알아보자

In [4]:
sp.plot_signals(time, signal, ma_output, lp_output, [1.2, 1.6])
Notebook output

Moving Average와 Low-Pass Filter

Moving Average (이동 평균)

정의: Moving Average는 시계열 데이터에서 노이즈를 제거하고 추세를 파악하기 위해 사용하는 필터다. 일정한 윈도우 크기 내의 데이터 포인트들의 평균을 계산한다.

수식:

y[n]=1Ni=0N1x[ni]y[n] = \frac{1}{N} \sum_{i=0}^{N-1} x[n-i]

여기서:

  • y[n]y[n]: 필터링된 출력 신호
  • x[n]x[n]: 입력 신호
  • NN: 윈도우 크기 (window size)

원리:

  • 각 시점에서 과거 NN개의 데이터 포인트의 평균을 계산한다
  • 노이즈는 랜덤하게 분포되어 있기 때문에 평균을 내면 상쇄되어 감소한다
  • 신호의 급격한 변화를 완화시켜 부드러운 곡선을 만든다

사용 예시:

  • 주식 가격의 추세 분석 (5일, 20일, 50일 이동평균선)
  • 센서 데이터의 노이즈 제거
  • 실시간 데이터 스무딩
  • 경제 지표 분석

장점: 구현이 간단하고 계산 비용이 낮다

단점: 지연(lag)이 발생하고, 급격한 변화에 대한 반응이 느리다


Low-Pass Filter (저역 통과 필터)

정의: Low-Pass Filter는 주파수 영역에서 고주파 성분을 차단하고 저주파 성분만 통과시키는 필터다. 신호 처리에서 노이즈(고주파)를 제거하고 원본 신호(저주파)를 유지하는 데 사용한다.

수식 (지수 이동 평균 기반):

y[n]=αx[n]+(1α)y[n1]y[n] = \alpha \cdot x[n] + (1 - \alpha) \cdot y[n-1]

여기서:

  • y[n]y[n]: 필터링된 출력 신호
  • x[n]x[n]: 입력 신호
  • α\alpha: 필터 계수 (0 < α\alpha < 1), 값이 작을수록 더 강한 필터링

원리:

  • 현재 입력값과 이전 출력값의 가중 평균을 계산한다
  • α\alpha 값이 작으면 이전 값의 영향이 커져서 더 부드러운 신호가 된다
  • 고주파 노이즈는 빠르게 변하기 때문에 필터링되어 감쇠되고, 저주파 신호는 유지된다

사용 예시:

  • 오디오 신호 처리 (고주파 노이즈 제거)
  • 이미지 처리 (블러 효과, 노이즈 제거)
  • 센서 데이터 필터링 (가속도계, 자이로스코프)
  • 통신 시스템 (신호 복원)
  • 생체 신호 처리 (ECG, EEG)

장점: 실시간 처리에 적합하고, 메모리 사용량이 적다

단점: Moving Average보다 계산이 약간 복잡하지만, 더 부드러운 결과를 제공한다


두 필터의 차이점

특성Moving AverageLow-Pass Filter
계산 방식과거 N개 데이터의 평균지수 가중 평균
메모리N개 데이터 저장 필요이전 출력값 1개만 저장
지연윈도우 크기에 비례상대적으로 적음
반응 속도느림상대적으로 빠름
부드러움중간높음
적용 분야추세 분석, 통계실시간 신호 처리
In [5]:
time = np.arange(0, 4 + 0.01, 0.01)
square_wave = np.where((time % 2) < 1, 0, 2)
noise = np.random.normal(0, 0.2, size=time.shape)
signal = square_wave + noise

plt.figure(figsize=(10, 4))
plt.plot(time, signal, label='Square Wave with Noise')
plt.plot(time, square_wave, label='Square Wave', linewidth=2, linestyle="--")
plt.xlabel("Time (sec)")
plt.ylabel("Square Wave (0 to 2) with Noise (σ=0.2)")
plt.legend()
plt.show()
Notebook output
In [6]:
sp = SignalProcessor(window_size=5, alpha=0.2)

ma_output = []
lp_output = []

for val in signal:
    ma_output.append(sp.moving_average(val))
    lp_output.append(sp.low_pass_filter(val))

sp.plot_signals(time, signal, ma_output, lp_output)
Notebook output
In [7]:
sp.plot_signals(time, signal, ma_output, lp_output, [0.9, 1.5])
Notebook output
In [8]:
time = np.arange(0, 2 + 0.01, 0.01)
signal = np.where(np.isclose(time, 1, atol=1e-8), 1, 0)

sp = SignalProcessor(window_size=5, alpha=0.5)

ma_output = []
lp_output = []

for val in signal:
    ma_output.append(sp.moving_average(val))
    lp_output.append(sp.low_pass_filter(val))

sp.plot_signals(time, signal, ma_output, lp_output, [0.75, 1.5])
Notebook output

확실히 low-pass filter 가 급격한 변화에 대한 반응을 더 잘 한다고 할 수 있다.