Fourier变换极其逆变换在数学上的定义如下
F ( ω ) = ∫ − ∞ ∞ f ( t ) e − i ω t d t f ( t ) = π 2 ∫ − ∞ ∞ F ( ω ) e i ω t d ω F(\omega)=\int^\infty_{-\infty}f(t)e^{-i\omega t}\text dt\\ f(t)=\frac{\pi}{2}\int^\infty_{-\infty}F(\omega)e^{i\omega t}\text d\omega F(ω)=∫−∞∞f(t)e−iωtdtf(t)=2π∫−∞∞F(ω)eiωtdω
scipy
中的Fourier变换函数位于fftpack
模块中,下表整理出一部分与Fourier变换相关的函数,其中FFT为快速Fourier变换(Fast Fourier Transform);DCT为离散余弦变换(Discrete Cosine Transform);DST为离散正弦变换(discrete sine transform),另外,函数的前缀有如下含义
i
表示逆变换;r
表示实数域,如开头无r
表示在复数域函数 | 说明 |
---|---|
fft, ifft, rfft, irfft | FFT算法 |
dct, idct | DCT算法 |
dst, idst | DST算法 |
fft2, ifft2 | 复数域二维FFT |
fftn, ifftn | 复数域高维FFT |
fftshift, ifftshift rfftshift, irfftshift | 移动FFT的频谱,使得直流分量占据中心 |
fftfreq | FFT计算结果所对应的频率 |
在数值计算中,一切输入输出均为离散值,所以实际上用到的是离散Fourier变换,即DFT,其功能是将离散的采样变换为一个离散的频谱分布。
下面将手动创建一组采样点,并添加一点噪声,然后通过FFT获取其频域信息。
import numpy as np
from scipy import fftpack
PI = np.pi*2
fs = 60 #采样频率
T = 100 #采样周期数
N = fs*T #采样点
t = np.linspace(0, T, N)
s = 2 * np.sin(PI * t) + 3 * np.sin(22 * PI * t) + 2 * np.random.randn(*t.shape)
F = fftpack.fft(s)
f = fftpack.fftfreq(N, 1.0/fs)
其中,t
为时间序列,s
为模拟的采样点,F
是Fourier变换之后的结果。但由于fft
默认是在复数域上的,故而可以查看其实部、虚部、模和辐角的值。
下面对采样点以及Fourier变换的结果进行绘制
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(2,2,1)
ax.plot(t, s)
ax.set_title("t vs s")
f_abs = np.abs(F)
ax = fig.add_subplot(2,2,2)
ax.plot(f, f_abs)
ax.set_title("fs vs |F|")
ax = fig.add_subplot(2,2,3)
ax.stem(f, f_abs)
ax.set_xlim([0,2])
ax.set_title("fs vs |F|")
ax = fig.add_subplot(2,2,4)
ax.stem(f, f_abs)
ax.set_title("fs vs |F|")
ax.set_xlim([21,23])
plt.show()
结果为
即 f = 1 f=1 f=1和 f = 22 f=22 f=22处被筛选了出来。
有了这个,就可以在频域上对数据进行滤波,其思路是,对f_abs
中的值进行阈值分割,例如,只筛选出低频部分,然后看一下滤波效果
fig = plt.figure(1)
f_filt = F * (np.abs(f) < 2)
s_filt = fftpack.ifft(f_filt)
ax = fig.add_subplot()
ax.plot(t, s, lw=0.2)
ax.plot(t, s_filt.real, lw=2)
ax.set_title("threshold=2")
ax.set_xlim([0,10])
plt.show()
效果如下