Numpy FFT实部/虚部/abs部件解释

Numpy FFT实部/虚部/abs部件解释,numpy,signal-processing,fft,complex-numbers,dft,Numpy,Signal Processing,Fft,Complex Numbers,Dft,我目前正在学习离散傅里叶变换,我正在玩numpy来更好地理解它 我试图绘制一个“sin x sin x sin”信号,得到了一个4个非零点的干净FFT。我天真地告诉自己:“如果我用这些振幅和频率绘制一个“sin+sin+sin+sin”信号,我应该得到相同的“sin x sin x sin”信号,对吗 嗯……不完全是 (第一个是“x”信号,第二个是“+”信号) 两者具有相同的振幅/频率,但不是相同的信号,即使我可以看到它们有一些相似之处 好的,因为我只画了FFT的绝对值,我想我丢失了一些信息

我目前正在学习离散傅里叶变换,我正在玩numpy来更好地理解它

我试图绘制一个“sin x sin x sin”信号,得到了一个4个非零点的干净FFT。我天真地告诉自己:“如果我用这些振幅和频率绘制一个“sin+sin+sin+sin”信号,我应该得到相同的“sin x sin x sin”信号,对吗

嗯……不完全是

(第一个是“x”信号,第二个是“+”信号)

两者具有相同的振幅/频率,但不是相同的信号,即使我可以看到它们有一些相似之处

好的,因为我只画了FFT的绝对值,我想我丢失了一些信息

然后,我绘制了两个信号的实部、虚部和绝对值:

现在,我很困惑。我该怎么办呢?我从数学的角度阅读了DFT。我知道复值来自单位圆。我甚至不得不学习希尔伯特空间来理解它是如何工作的(这很痛苦!…我只触及了表面).我只想了解这些真实/想象的情节在数学世界之外是否有任何具体意义:

  • abs(fft):频率+振幅
  • 实数(fft):
  • 想象(fft):
代码:

import numpy as np
import matplotlib.pyplot as plt
N = 512 # Sample count
fs = 128 # Sampling rate
st = 1.0 / fs # Sample time
t = np.arange(N) * st # Time vector

signal1 = \
1   *np.cos(2*np.pi * t) *\
2   *np.cos(2*np.pi * 4*t) *\
0.5 *np.cos(2*np.pi * 0.5*t)

signal2 = \
0.25*np.sin(2*np.pi * 2.5*t) +\
0.25*np.sin(2*np.pi * 3.5*t) +\
0.25*np.sin(2*np.pi * 4.5*t) +\
0.25*np.sin(2*np.pi * 5.5*t)



_, axes = plt.subplots(4, 2)

# Plot signal
axes[0][0].set_title("Signal 1 (multiply)")
axes[0][0].grid()
axes[0][0].plot(t, signal1, 'b-')

axes[0][1].set_title("Signal 2 (add)")
axes[0][1].grid()
axes[0][1].plot(t, signal2, 'r-')

# FFT + bins + normalization
bins = np.fft.fftfreq(N, st)    
fft  = [i / (N/2) for i in np.fft.fft(signal1)]
fft2 = [i / (N/2) for i in np.fft.fft(signal2)]

# Plot real
axes[1][0].set_title("FFT 1 (real)")
axes[1][0].grid()
axes[1][0].plot(bins[:N/2], np.real(fft[:N/2]), 'b-')

axes[1][1].set_title("FFT 2 (real)")
axes[1][1].grid()
axes[1][1].plot(bins[:N/2], np.real(fft2[:N/2]), 'r-')

# Plot imaginary
axes[2][0].set_title("FFT 1 (imaginary)")
axes[2][0].grid()
axes[2][0].plot(bins[:N/2], np.imag(fft[:N/2]), 'b-')

axes[2][1].set_title("FFT 2 (imaginary)")
axes[2][1].grid()
axes[2][1].plot(bins[:N/2], np.imag(fft2[:N/2]), 'r-')

# Plot abs
axes[3][0].set_title("FFT 1 (abs)")
axes[3][0].grid()
axes[3][0].plot(bins[:N/2], np.abs(fft[:N/2]), 'b-')

axes[3][1].set_title("FFT 2 (abs)")
axes[3][1].grid()
axes[3][1].plot(bins[:N/2], np.abs(fft2[:N/2]), 'r-')

plt.show()

对于每个频率单元,幅值
sqrt(re^2+im^2)
告诉您相应频率下分量的振幅。相位
atan2(im,re)
告诉您该组件的相对相位。实部和虚部本身并不特别有用,除非您对数据窗口中心周围的对称特性感兴趣(偶数与奇数).

关于某个参考点,例如固定时间窗口的中心,相同频率的正弦波和余弦波看起来会不同(相对于任何固定时间参考点具有不同的起始相位)。它们在数学上也将与任何整数周期宽度正交,因此可以表示变换的独立基向量分量

FFT结果的实部是每个频率分量与余弦波的相似程度,虚部是每个频率分量与正弦波的相似程度。正弦和余弦分量的各种比率一起可以构造任意或所需相位的正弦曲线,从而使FFT结果完整


单凭幅值无法区分正弦波和余弦波之间的差异。IFFT(imag(FFT))会破坏任何相位与纯余弦不同的信号的重建。与IFFT(re(FFT))和纯正弦波(相对于FFT孔径窗口)相同.

您可以将信号1(由三个cos函数的乘积组成)转换为四个cos函数的和。这使函数2(四个正弦函数的和)有所不同

cos函数是偶数函数cos(-x)==cos(x)。 偶数函数的傅里叶变换是纯实的。 这就是为什么函数1的fft虚部图只包含接近零的值(1e-15)的原因

正弦函数是奇数函数sin(-x)==-sin(x)。 奇数函数的傅里叶变换是纯虚函数。 这就是为什么函数2的fft实部曲线图仅包含接近零的值(1e-15)


如果您想更详细地了解FFT和DFT,请阅读电气工程信号分析教科书。

尽管……您现在必须是一名优秀的专家:) 对于其他人:请注意 因此,将总和修正为:

    signal1 = \
1   *np.cos(2*np.pi * t) *\
2   *np.cos(2*np.pi * 4*t) *\
0.5 *np.cos(2*np.pi * 0.5*t)

signal2 = \
0.25*np.cos(-2*np.pi * 2.5*t) +\
0.25*np.cos(2*np.pi * 3.5*t) +\
0.25*np.cos(-2*np.pi * 4.5*t) +\
0.25*np.cos(2*np.pi * 5.5*t)
现在给出以下结果


问题是,实数部分也应该是一样的,多亏了你和hotpaw2。我想我现在理解得更好了。我甚至不知道atan2的存在!问题:1)我假设复数平方的实数部分是正的,对吗?2)当复数平方时,它的虚部的符号是什么?是吗负数,因为sqrt(-1)**2是-1?@ox:不,把复数看作
re+j*im
。所以
re
im
都是实数,
re^2
im^2
都是正数。你是对的,我没有提交好的例子(sin/cos)嗯,我确实读过各种各样的教科书、网站、看视频、一个DSP mooc,但它们大多包含一些令人生畏的内容(至少对我来说)数学概念和公式,需要像这样做一些额外的研究。我开始理解它们,但我还有很长的路要走。感谢前面的答案,我现在可以通过添加余弦子信号手动重建任何信号(因为原始信号是真实的)有相应的震级和相位。相位公式是我遗漏的关键。这就是为什么我接受保罗R的答案