使用Python进行傅里叶变换

3

我正在尝试使用Python进行傅里叶变换。

有一个很好的库numpy,其中有函数fft,根据文档,它应该接收一系列点并返回它们的傅里叶变换。

现在我试图让它工作-但它看起来不对...

我创建了一个简单的1Hz正弦波振幅=1。 我用8Hz(即8个样本)对其进行采样

这些是样本:

[0,0.707,1,0.707,0,-0.707,-1,-0.707]

现在我期望得到[0,4,0,0,0,0,0,4][0,8,0,0],表示频率为1Hz(取决于是否按照奈奎斯特极限所需进行修剪)。

但实际上我得到了以下结果:

[0.00000000e+00+0.00000000e+00j, -2.22044605e-16-3.99969798e+00j,
 0.00000000e+00+0.00000000e+00j, -2.22044605e-16+3.02022804e-04j,
 0.00000000e+00+0.00000000e+00j,  2.22044605e-16-3.02022804e-04j,
 0.00000000e+00+0.00000000e+00j,  2.22044605e-16+3.99969798e+00j]

这是我的代码:
import numpy
signal = numpy.array([0,0.707,1,0.707,0,-0.707,-1,-0.707], dtype=float)
f =  numpy.fft.fft(signal)
print (f)

为什么我会得到这个结果?我做错了什么吗?


3
尝试使用余弦函数而不是正弦函数。 - Oliver Charlesworth
这些是样本:[0,0.707,1,0.707,0,-0.707,-1,-0.707]。如果您将“0.707”替换为更精确的值“np.sqrt(2)/2”,则可以显著减少数值噪声。 - Warren Weckesser
出于好奇,为什么这会帮助OP呢? - tel
@OliverCharlesworth 说得有道理,谢谢。这个问题对物理201课程来说是一个很好的复习。 - tel
可能是Proving Fourier transform operation in Python的重复问题。 - Cris Luengo
显示剩余2条评论
1个回答

1

傅里叶变换的输出

numpy.fft.fft(以及其他所有傅里叶变换方法)的输出具有复杂值。此输出编码了输入中每个频率分量的振幅和相位移信息。您在输出中获得的复数是正确的。

如何从fft.fft的输出获取频谱

从您的示例中,您似乎正在尝试获取的输出实际上是频谱(技术上称为能量谱密度)。您可以通过仅对numpy.fft.fft返回的结果取绝对值来计算此值:

import numpy
signal = numpy.array([0,0.707,1,0.707,0,-0.707,-1,-0.707], dtype=float)
f =  numpy.fft.fft(signal)
print(np.abs(f))

输出:

[0.00000000e+00 3.99969798e+00 0.00000000e+00 3.02022804e-04
 0.00000000e+00 3.02022804e-04 0.00000000e+00 3.99969798e+00]

这正是您所期望的,但存在一定的数值误差。

根据Warren Weckesser的评论,您可以通过使用“实际”值2 ** .5 / 2代替简写的 .707 来减少数值误差:

signal = numpy.array([0, 2**.5/2, 1, 2**.5/2, 0, -2**.5/2, -1, -2**.5/2])
f =  numpy.fft.fft(signal)
print(np.abs(f))

输出:

[0.00000000e+00 4.00000000e+00 0.00000000e+00 2.22044605e-16
 0.00000000e+00 2.22044605e-16 0.00000000e+00 4.00000000e+00]

复数的绝对值是它的大小。根据傅里叶变换百科所述:
在某一点处的傅里叶变换的大小表示频率内容的多少。

取绝对值表面上解决了问题,但是不正确,也不能推广到其他输入函数。问题在于OP错误地期望输入信号的原点(以及输出)。请参见建议的重复问题。 - Cris Luengo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接