SciPy 푸리에 변환 (FFT)
1. 서론
디지털 신호 처리에서 푸리에 변환(Fourier Transform)은 시간 영역의 신호를 주파수 영역으로 변환하는 중요한 도구입니다. 이 과정은 복잡한 신호를 다양한 주파수 성분으로 분해하여 분석하고 이해하는 데 도움을 줍니다. SciPy는 빠른 푸리에 변환(Fast Fourier Transform, FFT) 기능을 제공하여 효율적으로 신호를 분석할 수 있도록 지원합니다.
이 글에서는 SciPy의 scipy.signal과 scipy.fft 모듈을 활용하여 푸리에 변환을 수행하고, 신호 분석 방법을 설명하겠습니다. 또한, 예제 코드를 통해 실습을 진행하면서 푸리에 변환의 실제 활용 방법을 익혀보겠습니다.
2. 푸리에 변환의 개념
2.1 시간 영역과 주파수 영역
- 시간 영역(Time Domain): 신호의 진폭이 시간에 따라 변하는 모습을 나타낸 것입니다. 우리가 일반적으로 보는 오디오 신호의 파형은 시간 영역에서 표현된 것입니다.
- 주파수 영역(Frequency Domain): 신호를 구성하는 다양한 주파수 성분과 각 성분의 진폭 및 위상을 나타낸 것입니다.
2.2 푸리에 변환과 역변환
푸리에 변환은 다음과 같이 정의됩니다.
$$
X(f) = \int_{-\infty}^{\infty} x(t) e^{-j 2 \pi f t} dt
$$
여기서:
- $ x(t) $: 시간 영역의 신호
- $ X(f) $: 주파수 영역의 신호
- $ j $: 허수 단위
역 푸리에 변환(Inverse Fourier Transform) 역시 비슷한 형태로 정의되며, 주파수 영역에서 시간 영역으로 변환하는 역할을 합니다.
2.3 빠른 푸리에 변환 (FFT)
FFT(Fast Fourier Transform)는 푸리에 변환을 빠르게 계산하는 알고리즘입니다. 일반적인 푸리에 변환의 계산 복잡도는 $O(N^2)$이지만, FFT는 $O(N \log N)$의 복잡도로 처리할 수 있어 실시간 신호 처리와 대규모 데이터 분석에 적합합니다.
3. SciPy에서 FFT 활용하기
SciPy는 scipy.fft 모듈을 통해 FFT와 역 FFT를 손쉽게 수행할 수 있도록 지원합니다. 다음은 기본적인 사용 방법입니다.
3.1 기본 FFT 수행
아래는 사인파 신호에 대해 FFT를 수행하는 간단한 예제입니다.
import numpy as np
import matplotlib.pyplot as plt
from scipy.fft import fft, fftfreq
# 샘플링 파라미터
fs = 1000 # 샘플링 주파수 (Hz)
t = np.linspace(0, 1, fs, endpoint=False) # 1초 동안의 시간 축
signal = np.sin(2 * np.pi * 50 * t) + 0.5 * np.sin(2 * np.pi * 120 * t)
# FFT 수행
fft_result = fft(signal)
frequencies = fftfreq(len(fft_result), 1 / fs)
# 주파수 성분 시각화
plt.figure(figsize=(12, 6))
plt.plot(frequencies[:fs // 2], np.abs(fft_result)[:fs // 2] * 2 / fs)
plt.title("FFT 결과: 주파수 영역")
plt.xlabel("주파수 (Hz)")
plt.ylabel("진폭")
plt.grid(True)
plt.show()
이 예제에서는 50Hz와 120Hz의 사인파를 합친 신호에 대해 FFT를 수행하고, 주파수 스펙트럼을 시각화하였습니다.
3.2 역 FFT 수행
FFT로 주파수 영역에서 분석한 데이터를 다시 시간 영역으로 변환하는 역 FFT(Inverse FFT)도 가능합니다.
from scipy.fft import ifft
# 역 FFT 수행
reconstructed_signal = ifft(fft_result)
# 원본 신호와 비교
plt.figure(figsize=(12, 6))
plt.plot(t, signal, label='원본 신호')
plt.plot(t, reconstructed_signal.real, '--', label='복원된 신호')
plt.title("원본 신호와 복원된 신호 비교")
plt.xlabel("시간 (초)")
plt.ylabel("진폭")
plt.legend()
plt.grid(True)
plt.show()
역 FFT를 통해 원본 신호와 거의 동일한 신호를 복원할 수 있음을 확인할 수 있습니다.
4. 실제 데이터에 적용하기
실제 오디오 데이터나 센서 데이터를 FFT를 활용해 분석하는 과정도 가능합니다. 다음은 랜덤 신호에 노이즈를 추가하고, FFT를 통해 노이즈를 제거하는 예제입니다.
# 노이즈가 포함된 신호 생성
noisy_signal = signal + 0.3 * np.random.normal(0, 1, len(t))
# FFT 수행
fft_noisy = fft(noisy_signal)
# 노이즈 제거: 일정 진폭 이하의 주파수 성분 제거
threshold = 10
filtered_fft = np.where(np.abs(fft_noisy) > threshold, fft_noisy, 0)
# 역 FFT로 복원
filtered_signal = ifft(filtered_fft)
# 시각화
plt.figure(figsize=(12, 8))
plt.subplot(3, 1, 1)
plt.plot(t, noisy_signal, label='노이즈가 포함된 신호')
plt.legend()
plt.grid(True)
plt.subplot(3, 1, 2)
plt.plot(frequencies[:fs // 2], np.abs(filtered_fft)[:fs // 2] * 2 / fs)
plt.title("필터링된 주파수 성분")
plt.grid(True)
plt.subplot(3, 1, 3)
plt.plot(t, filtered_signal.real, label='노이즈 제거된 신호')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
이 예제에서는 FFT를 이용해 노이즈를 제거하고, 깔끔한 신호를 복원하는 방법을 시연했습니다.
5. 고급 활용 방법
5.1 고속 역변환 (IFFT)
SciPy의 ifft는 주파수 영역의 데이터를 다시 시간 영역으로 변환하는 데 사용됩니다. 필터링된 신호를 다시 시간 영역으로 복원할 때 유용합니다.
5.2 2D 및 다차원 푸리에 변환
scipy.fft.fft2와 scipy.fft.fftn을 사용하면 2차원 이미지 데이터나 다차원 신호에 대해 푸리에 변환을 수행할 수 있습니다.
from scipy.fft import fft2, ifft2
# 2D 이미지에 FFT 적용
image = np.random.rand(256, 256)
image_fft = fft2(image)
image_reconstructed = ifft2(image_fft)
print("원본과 복원된 이미지의 차이:", np.abs(image - image_reconstructed).max())
6. 결론
SciPy의 FFT 기능을 활용하면 시간 영역의 신호를 주파수 영역으로 변환하여 다양한 분석과 처리를 수행할 수 있습니다. 푸리에 변환은 오디오, 이미지, 센서 데이터 분석 등 다양한 분야에서 필수적인 도구로, 신호의 특성을 깊이 이해하고 필요에 따라 데이터를 필터링하거나 복원하는 데 큰 도움이 됩니다.
다양한 FFT 활용 방법을 익히면 디지털 신호 처리에서 더 강력한 분석 능력을 갖출 수 있을 것입니다.
'Python for AI, Embedded > Data Science: NumPy, Pandas, SciPy' 카테고리의 다른 글
| SciPy 신호 간 상관 분석 (0) | 2025.11.29 |
|---|---|
| SciPy 주파수 분석과 스펙트로그램 (0) | 2025.11.28 |
| SciPy를 활용한 필터 설계 및 적용 (butter, filtfilt) (0) | 2025.11.26 |
| SciPy.optimize: 제약 조건과 경계 설정 방법 (0) | 2025.11.25 |
| SciPy를 활용한 곡선 맞추기 (curve_fit) (0) | 2025.11.24 |