傅里叶变换的内在原理
一、基底的原理
众所周知,对于任意一个函数来说,都可以将其分解为多个正弦函数和余弦函数相互叠加的形式,并使用欧拉公式进行转换,可以得到:
f
(
x
)
=
a
0
2
+
∑
n
=
1
∞
(
a
n
cos
(
2
π
n
x
T
)
+
b
n
sin
(
2
π
n
x
T
)
)
f(x)=\frac{a_0}{2}+\sum_{n=1}^{\infty}(a_n\cos(\frac{2\pi nx}{T})+b_n\sin(\frac{2\pi nx}{T}))
f(x)=2a0+n=1∑∞(ancos(T2πnx)+bnsin(T2πnx))
很明显,可以使用一组正交基来表示,即:
B
=
{
sin
(
w
1
x
)
,
cos
(
w
1
x
)
,
sin
(
w
2
x
)
,
cos
(
w
2
x
)
,
.
.
.
,
sin
(
w
n
x
)
,
cos
(
w
n
x
)
}
B = \{\sin(w_1x), \cos(w_1x), \sin(w_2x), \cos(w_2x),...,\sin(w_nx), \cos(w_nx)\}
B={sin(w1x),cos(w1x),sin(w2x),cos(w2x),...,sin(wnx),cos(wnx)}
其中,正交基的概念是:在一个周期内,它们任意两个的内积为0,即存在:
∫
−
T
2
T
2
sin
(
w
1
x
)
sin
(
w
2
x
)
d
x
=
0
w
1
≠
w
2
∫
−
T
2
T
2
cos
(
w
1
x
)
cos
(
w
2
x
)
d
x
=
0
w
1
≠
w
2
∫
−
T
2
T
2
sin
(
w
1
x
)
cos
(
w
2
x
)
d
x
=
0
\begin{split} \int_{-\frac{T}{2}}^{\frac{T}{2}}\sin(w_1x)\sin(w_2x)dx&=0 \quad w_1\neq w_2 \\ \int_{-\frac{T}{2}}^{\frac{T}{2}}\cos(w_1x)\cos(w_2x)dx&=0 \quad w_1\neq w_2 \\ \int_{-\frac{T}{2}}^{\frac{T}{2}}\sin(w_1x)\cos(w_2x)dx&=0 \\ \end{split}
∫−2T2Tsin(w1x)sin(w2x)dx∫−2T2Tcos(w1x)cos(w2x)dx∫−2T2Tsin(w1x)cos(w2x)dx=0w1=w2=0w1=w2=0
换句话说,当某个时域函数 f ( x ) f(x) f(x)看成多个正弦和余弦函数的相互叠加后,如果需要判断某个三角函数是否存在,就只需要对其内积一个相同的三角函数。当内积之后的值为0时,则说明 f ( x ) f(x) f(x)中不存在这个三角函数,反之则存在。
二、基于欧拉公式的进一步理解
而在欧拉公式中,存在:
e
i
x
=
cos
x
+
i
sin
x
e^{ix}=\cos{x}+i\sin{x}
eix=cosx+isinx
f
(
x
)
f(x)
f(x)就可以修改为:
f
(
x
)
=
∑
n
=
−
∞
∞
c
n
⋅
e
i
2
π
n
x
T
d
x
f(x)=\sum_{n=-\infty}^{\infty}c_n\cdot e^{i\frac{2\pi nx}{T}}dx
f(x)=n=−∞∑∞cn⋅eiT2πnxdx
因此,可以将前面的基底B简化成:
B
=
{
1
,
e
w
1
x
,
e
w
2
x
,
.
.
.
,
e
w
n
−
1
x
}
B=\{1, e^{w_1x}, e^{w_2x}, ..., e^{w_{n-1}x}\}
B={1,ew1x,ew2x,...,ewn−1x}
因此,当给予
f
(
x
)
f(x)
f(x)分别内积矩阵B的各个元素时,就能够判断各项因子是否存在。
此外,由于
e
−
i
x
=
cos
(
−
x
)
+
i
sin
(
−
x
)
=
cos
x
−
i
sin
x
=
e
^
i
x
e^{-ix}=\cos{(-x)}+i\sin{(-x)}=\cos{x}-i\sin{x}={\hat{e}^{ix}}
e−ix=cos(−x)+isin(−x)=cosx−isinx=e^ix
所以,也能以
B
^
\hat{B}
B^作为一组基底,而这个,也就是傅里叶变换的基底
W
n
i
W_n^i
Wni。
换个角度,
e
i
x
e^{ix}
eix和
e
−
i
x
e^{-ix}
e−ix都是表示一个单位圆,只是,
e
i
x
e^{ix}
eix是沿逆时针旋转,而
e
−
i
x
e^{-ix}
e−ix是沿顺时针旋转。
三、幅值和相位(傅里叶变换后的y、x轴)
3.1 幅值
前面说到,对
f
(
x
)
f(x)
f(x)内积一个基底时,如果基底存在,那么它们的内积则不为0。这里以幅值为1的正弦函数作为举例,有:
∫
−
T
2
T
2
sin
(
w
i
x
)
sin
(
w
i
x
)
d
x
=
1
2
∫
−
T
2
T
2
1
−
cos
(
2
w
i
x
)
d
x
=
T
2
\begin{split} &\int_{-\frac{T}{2}}^{\frac{T}{2}}\sin(w_ix)\sin(w_ix)dx \\ =&\frac{1}{2}\int_{-\frac{T}{2}}^{\frac{T}{2}}1-\cos(2w_ix)dx \\ =&\frac{T}{2} \end{split}
==∫−2T2Tsin(wix)sin(wix)dx21∫−2T2T1−cos(2wix)dx2T
同理,就有:
a
∫
−
T
2
T
2
sin
(
w
i
x
)
⋅
[
−
j
sin
(
w
i
x
)
]
d
x
=
−
T
2
j
a
a
∫
−
T
2
T
2
cos
(
w
i
x
)
cos
(
w
i
x
)
d
x
=
T
2
a
\begin{split} a\int_{-\frac{T}{2}}^{\frac{T}{2}}\sin(w_ix)\cdot[-j\sin(w_ix)]dx &=-\frac{T}{2}ja \\ a\int_{-\frac{T}{2}}^{\frac{T}{2}}\cos(w_ix)\cos(w_ix)dx &=\frac{T}{2}a \\ \end{split}
a∫−2T2Tsin(wix)⋅[−jsin(wix)]dxa∫−2T2Tcos(wix)cos(wix)dx=−2Tja=2Ta
因此,就可以通过傅里叶变换得到的实部和虚部,就能分别判断余弦函数和正弦函数,以及对应的幅值a。
3.2 相位
现在,再次从相位的角度去看基底。当内积一个基底 W n i = e − j 2 π T i x W_n^i=e^{-j\frac{2\pi}{T}ix} Wni=e−jT2πix时,就说明此时基底的相位为 1 T i \frac{1}{T}i T1i。因此,当内积不趋于0时,就说明f(x)存在相同相位的函数。
四、代码实验
4.1 原理验证
这里,选择直接调用fft函数进行快速傅里叶变换,并假定时域采样数量与频域采样数量一致。
clc, clear
N = 3000; % 设置5000个采样点
x = linspace(0, 1, N); % 将0到1平分成5000份
y1 = 7 * sin(2 * pi * 300 * x) + ...
5 * sin(2 * pi * 400 * x) + ...
3 * sin(2 * pi * 600 * x) + 10; % 构造一个正弦组合信号,10为偏移信号
fft_y1 = fft(y1); % 使用快速傅里叶变换,得到的fft_y是长度为N的复数数组
freq_x = x * N;
plot(freq_x, w1)
w1 = zeros(1, N);
% 第一项为电流偏移信号
w1(1) = fft_y1(1) / N;
w1(2:end) = -imag(fft_y1(2:end)) / (N / 2);
plot(x, w1)
w1(w1<1&w1>-1) = 0;
freq_list1 = find(w1); % 找出不为0的数的下标
w1 = w1(freq_list1);
disp('相位为:')
disp(freq_list1 - 1)
disp('幅值为:')
disp(w1)
输出的图像和结果如下所示:
哎,相位和幅值数据为什么多了一半,而且幅值还互为相反数?
这是因为,基底采样数量是在一个周期的,即
[
0
,
T
]
[0,T]
[0,T]。这个解释起来很简单。就以基础的正弦函数来说,它是关于原点对称的。这也就意味着,当采样的角度范围为
[
0
,
π
]
[0, \pi]
[0,π]时,它实际上就能够基于一组基底,判断出所有的幅值。而当角度变为
[
T
2
,
T
]
[\frac{T}{2}, T]
[2T,T],它所计算出的值自然就关于
π
\pi
π即实例中的采样范围中心点freq=1500对称。
4.2 幅值精度优化
此外,可以看到,计算出的幅值与实际幅值差异有点大,这是因为实际计算中会产生累计的计算误差、以及相位偏移等因素影响。有什么方法可以提高精度呢?增加采样点数量?可以是可以,但这样也会大幅增加计算成本和数据成本。因此,一种很好的方法就是计算对应基底计算的总幅值,即看计算结果的模值。虽然,这种方法不能区分正弦函数和余弦函数单独的幅值,但是,它们的模值却可以表示两者合成后的总幅值,进而降低误差的影响。
w11 = abs(fft_y1);
w11(1) = w11(1) / N;
w11(2:end) = w11(2:end) / (N / 2);
w11(w11<1) = 0;
freq_list11 = find(w11); % 找出不为0的数的下标
w11 = w11(freq_list11);
disp('相位为:')
disp(freq_list11 - 1)
disp('幅值为:')
disp(w11)
4.3 正弦和余弦叠加的函数
最后,以一个复杂的叠加信号进行验证,从运行结果来看,猜想没有问题,只是,依旧存在较大误差,而它们叠加后的模值同样精度更高。
N = 30000;
x = linspace(0, 1, N);
y2 = 7 * sin(2 * pi * 300 * x) + 6 * cos(2 * pi * 300 * x) + ...
5 * sin(2 * pi * 400 * x) + 4 * cos(2 * pi * 400 * x) + ...
3 * sin(2 * pi * 600 * x) + 2 * cos(2 * pi * 600 * x) + 10; % 构造一个复杂的组合信号,10为偏移信号
fft_y2 = fft(y2); % 使用快速傅里叶变换
w2 = zeros(1, N);
w2(1) = fft_y2(1) / N;
w2(2:end) = conj(fft_y2(2:end)) / (N / 2);
w2(abs(w2)<1) = 0;
freq_list2 = find(w2);
w2 = w2(freq_list2);
disp('相位为:')
disp(freq_list2 - 1)
disp('幅值为:')
disp(w2)