본문 바로가기

Python

Python으로 신호 푸리에 변환하는 방법

320x100
320x100

 

 

 신호 처리를 하다 보면 가장 먼저 접하게 되는 개념이 '푸리에 변환'이다. 이번 글에서는 파이썬의 numpy를 통해 푸리에 변환하는 방법에 대해 정리하고자 한다. 그 전에... 푸리에 변환에 대한 이론적 배경을 정확하게 알고있는 게 아니라 틀린 부분이 있을 수 있다는 점을 미리 밝힙니다!!

 

푸리에 변환 (Fourier transform)

 

시간 영역에서 표현되는 신호를 주파수 영역으로 변환하여 다른 관점에서 신호를 분석하는 방법

 

 

 Python에서 푸리에 변환을 하고 싶으면 np.fft.fft( ) 함수를 아래와 같이 이용하면 된다.

import numpy as np
import matplotlib.pyplot as plt

fs = 100 
t = np.arange(0, 3, 1 / fs)
f1 = 35
f2 = 10
signal = 0.6 * np.sin(2 * np.pi * f1 * t) + 3 * np.cos(2 * np.pi * f2 * t + np.pi/2)

fft = np.fft.fft(signal) / len(signal)  

fft_magnitude = abs(fft)
  • [Line 4~8]
    35Hz를 갖는 0.6 진폭의 신호와 10Hz를 갖는 3 진폭 신호를 생성한 뒤,
    두 신호를 더하여 설명에 사용할 신호를 생성한다.
  • [Line 10]
    생성된 신호를 np.fft.fft( ) 함수로 푸리에 변환 시킨다.
    여기서 중요한 점은,
    함수의 반환값 (여기서는 fft 변수에 저장)을 신호의 길이로 나눠줘야 한다는 점!
    바꿔말하면 normalization 해줘야하는 다는 건데, 안 해주면 Line 12의 fft_magnitude 값이 엄청 커진다.
    그래야 분석 대상 신호를 만들때 설정한 진폭 (각각 0.6 과 3)에 맞춰서 magnitude 그래프가 그려진다.
    np.fft.fft( ) 결과에 왜 normalization을 적용해야만 하는지 설명해주는 사이트는 아직 찾지 못 했다.
  • [Line 12]
    푸리에 변환 결과를 통해 우리가 얻을 수 있는 그래프는 두 종류가 있다.
       (1) 푸리에 스펙트럼 그래프 : 주파수에 따른 magnitude 그래프
       (2) 위상 그래프 : 주파수에 따른 angle 그래프
    우리가 원하는 건 magnitude 그래프이고,
    이를 얻기 위해선 복소수 타입인 np.fft.fft( ) 함수 반환값에 절대값을 취해주면 된다.

 

 생성된 신호와 푸리에 변환 결과를 표현하면 다음과 같다.

plt.subplot(2,1,1)
plt.plot(t,signal)
plt.grid()

plt.subplot(2,1,2)
plt.stem(fft_magnitude)
plt.ylim(0,2.5)
plt.grid()
plt.show()​

 

 뭔가 이상하다. 우리가 생각했던 결과와는 다르게 나타나는 것 같이 보인다. magnitude 값은 뭔가 맞는 것 같으면서도 x축을 보니 너무도 다르다. 그 이유에 알아보자.

  1. np.fft.fft( )는 반환값을 '양의 영역 다음에 음의 영역 순서'로 반환한다.
    그래서 위의 그래프를 기존으로 0~149는 양의 영역 / 150 ~ 299는 음의 영역에 해당되는 값들이다.
    우리는 제대로 된 그래프를 얻기 위해선 이를 음 → 양 순서로 바꿔줘야한다.
  2. x축이 이상하게 잡힌 건 Line 6에서 stem 그래프를 그려줄 때 x축을 지정 안 해줬기 때문이다.
    우리는 위에서 fs = 100Hz로 잡았기 때문에 x축이 -50Hz ~ 50Hz가 되도록 설정해줘야 한다.

 

 이제 문제 해결을 위해 다음의 코드를 사용하면 된다.

length = len(signal)
f = np.linspace(-(fs / 2), fs / 2, length)   

plt.stem(f, np.fft.fftshift(fft_magnitude)) 
plt.ylim(0,2.5)
plt.grid()

plt.show()​
  • [Line 1,2]
    stem 그래프의 x축을 지정해주는 코드이다. x축 변수를 새로 생성해서 맞춰준다 생각하면 된다.
    np.linspace( start, end, num )은 start로 시작해 end까지 num개의 변수를 일정한 간격으로 생성해주는 함수이다.
    따라러 변수 f에는 -50 ~ 50까지 일정한 간격으로 생성된 300개의 데이터가 저장된다.
  • [Line 4]
    np.fft.fftshift( )는 위에서 말한 np.fft.fft( ) 반환 값의 순서를 '음 → 양' 으로 변경해주는 함수이다.

 

 최종 결과를 그래프로 표현해보면 다음과 같음.

 

f : -35, -10, 10, 35 에서 magnitude : 0.3, 1.5, 1.5, 0.3 으로 그려지는 것을 확인할 수 있다. 이 그래프가 위에서 생성한 신호의 최종 푸리에 변환 그래프이다. 만약 양의 영역만 확인하고 싶다면 indexing을 해주면 된다.

 

 

 

https://pinkwink.kr/708 의 설명을 참고했습니다.」

 

 

 

! 광고 보고 끝 !

 

728x90
728x90