본문으로 바로가기

디지털 필터에 대해서는 예전에 많이 다루었는데요. 당시에 다룰때는 간단히 Python의 함수(def)를 사용해서 많이 다루었습니다. 이번에는 class를 이용해서 조금 사용성을 높인 코드를 보여드리는 것이 어떨까하고 글을 작성합니다. 일단 1차 저역통과필터는 예전에 소개한 글에서 수식을 가져오겠습니다.

저 식을 코드로 단순 변환 시켜보면 

out = (tau * pre_out + ts * data) / (tau + ts)

입니다. 수식에서 분모가 같으니 tau + ts는 빼서 보면 저렇게 되죠. 문제는 pre_out입니다. 현재 출력값 out, 수식에서는 yn의 이전 값이거든요. 그래서 저 코드가 실행된 직후 현재 출력을 별도로 저장해야 합니다. 만약 class를 사용하지 않는다면, 1차 저역통과필터가 필요할때마다 만들어야할 변수 때문에 고생을 하겠죠. 저 핵심 코드를 코함해서 간단히 클래스로 만들어 보겠습니다.

import numpy as np

class LowPassFilter:
    def __init__(self, cutoff_freq, ts):
        self.ts = ts
        self.cutoff_freq = cutoff_freq
        self.pre_out = 0.
        self.tau = self.calc_filter_coef() 
        
    def calc_filter_coef(self):
        w_cut = 2*np.pi*self.cutoff_freq
        return 1/w_cut
        
    def filter(self, data):
        out = (self.tau * self.pre_out + self.ts * data) / (self.tau + self.ts)
        self.pre_out = out
        return out

어떤가요. 입력 부분만 조금 편하게 Hz 단위의 차단 주파수를 넣었습니다. 선언하는 방법은

lpf = LowPassFilter(cutoff_freq = 0.5, ts = 0.01)

이렇게 차단 주파수를 0.5Hz로 샘플링타임을 0.01로 잡아주면 되겠죠. 필터를 한 번 테스트해보겠습니다.

import matplotlib.pyplot as plt
%matplotlib inline

t = np.arange(0, 10, 0.01)
y = np.sin(t)
plt.plot(t, y);

간단하게 0부터 10초까지 0.01초 간격으로 sin 함수를 만들어 둡니다.

이렇게 생겼습니다. 이제 잡음을 살짝 입히도록 하죠 

y = 10*np.sin(t) + 5*np.random.rand(len(y))
plt.plot(t, y);

이렇게 두겠습니다. 이 결과는 

이렇게 생겼습니다. 이제 아까 선언해둔 lpf를 적용시켜보죠.

filtered_data = [lpf.filter(data) for data in y]
plt.plot(t, y)
plt.plot(t, filtered_data, 'r', lw=3);

코드는 이렇게 사용하면 됩니다. 이제 결과를 보겠습니다.

타임 딜레이가 있지만, 연습용이니까요.^^. 0.5Hz 차단 주파수는 역시 좀 심했군요^.^ 아무튼 노이즈 들어간 신호를 잘 잡았네요. 이제 저역통과필터가 필요하신 분들은 위 class를 가져다 사용하시면 되겠습니다.^^


댓글을 달아 주세요

  1. Sericean 2021.03.19 09:59

    정말 유용한 정보네요. 클래스로 구현한 필터라니.. 클래스 사용이 익숙해져야 하는데 아직까지는 제한적으로만 사용해서 걱정이빈다ㅠㅠ

  2. BlogIcon 북두협객 2021.03.19 10:54

    상당히 훌륭한 코딩입니다! ㅎㅎ;;
    아주 좋아요 굿이에요.. ^^

  3. BlogIcon 드래곤포토 2021.03.20 14:34 신고

    즐거운 주말 보내세요

  4. BlogIcon 핑구야 날자 2021.03.21 07:33 신고

    잘 보고 갑니다 공식이 들어가는 코딩은 좀 어렵네요