에듀테크 프로젝트 대시보드
푸리에 변환
아무리 복잡하게 생긴 신호도 단순한 사인파 여러 개의 합으로 쪼갤 수 있다 — 이것이 푸리에의 아이디어다.
모든 것의 재료가 되는 사인파는 세 가지 숫자로 완전히 결정된다. 진폭(amplitude)은 높이, 주파수(frequency)는 1초에 반복되는 횟수, 위상(phase)은 출발 지점이다.
y(t) =
주파수가 1f, 2f, 3f인 사인파(배음, harmonics) 세 개의 진폭을 조절해 보자.
아래 왼쪽은 세 파형을 더한 결과, 오른쪽은 각 성분의 크기를 막대로 나타낸 주파수 스펙트럼이다.
막대 = 각 주파수 성분의 진폭. 이 그림이 바로 그 소리의 "지문"이다.
위에서는 사인파를 더해 파형을 만들었다. 푸리에 변환은 그 반대다. 완성된 파형만 주고 "이 안에 어떤 주파수가 얼마나 들어 있냐?"를 계산해 낸다. 아래 "미스터리 신호"에는 세 개의 주파수가 숨어 있다. 분석 버튼을 누르면 DFT가 그것을 찾아낸다.
버튼을 눌러 숨은 주파수를 찾아보세요.
놀랍게도 각진 사각파조차 사인파의 합이다. 홀수 배음(1f, 3f, 5f, 7f…)을
1, 1/3, 1/5, 1/7… 크기로 더하면 된다. 항을 늘릴수록 점점 사각형에 가까워진다.
다만 모서리에서 삐죽 튀는 깁스 현상(Gibbs phenomenon)은 항을 무한히 더해도 사라지지 않는다.
회색 = 목표 사각파, 하늘색 = 5개 항으로 만든 근사
정의는 딱 한 줄이다. 각 주파수 k에 대해, 신호와 그 주파수의 회전하는 파동을 곱해 전부 더한다.
실제로는 이 O(N²) 계산을 O(N log N)으로 줄인 FFT(고속 푸리에 변환)를 쓴다.
import cmath
def dft(x):
N = len(x)
X = []
for k in range(N): # 주파수 k
s = 0
for n in range(N): # 신호의 각 샘플
angle = -2j * cmath.pi * k * n / N
s += x[n] * cmath.exp(angle)
X.append(s)
return X # X[k] = 진폭 + 위상 (복소수)
signal = [ ... ] # 시간 영역 샘플
spectrum = dft(signal)
magnitude = [abs(v) / len(signal) for v in spectrum] # 각 주파수의 세기
| 개념 | 뜻 |
|---|---|
| 시간 영역 | 시간에 따른 신호의 값 (우리가 보통 보는 파형) |
| 주파수 영역 | 어떤 주파수가 얼마나 들어 있는지 (스펙트럼) |
| 푸리에 변환 | 시간 영역 → 주파수 영역으로 바꾸는 계산 |
| 역변환 | 주파수 성분을 다시 더해 원래 파형 복원 |
| FFT | DFT를 훨씬 빠르게 계산하는 알고리즘 (O(N log N)) |