【问题标题】:Fourier transform of a Gaussian is not a Gaussian, but thats wrong! - Python高斯的傅里叶变换不是高斯,但那是错误的! - Python
【发布时间】:2011-03-22 21:52:12
【问题描述】:

我正在尝试利用 Numpy 的 fft 函数,但是当我给该函数一个简单的高斯函数时,该高斯函数的 fft 不是高斯函数,它接近但减半,因此每一半都位于 x 轴的任一端.

我正在计算的高斯函数是 y = exp(-x^2)

这是我的代码:

from cmath import *
from numpy import multiply
from numpy.fft import fft
from pylab import plot, show

""" Basically the standard range() function but with float support """
def frange (min_value, max_value, step):
    value = float(min_value)
    array = []
    while value < float(max_value):
        array.append(value)
        value += float(step)
    return array


N = 256.0 # number of steps
y = []
x = frange(-5, 5, 10/N)

# fill array y with values of the Gaussian function   
cache = -multiply(x, x)
for i in cache: y.append(exp(i))

Y = fft(y)

# plot the fft of the gausian function
plot(x, abs(Y))
show()

结果不太对,因为高斯函数的FFT应该是高斯函数本身...

【问题讨论】:

  • 你可能想看看numpy.arange()

标签: python numpy fft


【解决方案1】:

np.fft.fft 以所谓的“标准顺序”返回结果:(from the docs)

如果A = fft(a, n),那么A[0] 包含零频率项( 信号的平均值),它总是 纯粹真实的真实输入。然后 A[1:n/2] 包含 正频率项,和 A[n/2+1:] 包含 负频率项,按顺序 负频率递减。

np.fft.fftshift 函数将结果重新排列成大多数人期望的顺序(这对绘图很有好处):

套路np.fft.fftshift(A) 变换变换及其 频率把零频率 中间的组件...

所以使用np.fft.fftshift

import matplotlib.pyplot as plt
import numpy as np

N = 128
x = np.arange(-5, 5, 10./(2 * N))
y = np.exp(-x * x)
y_fft = np.fft.fftshift(np.abs(np.fft.fft(y))) / np.sqrt(len(y))
plt.plot(x,y)
plt.plot(x,y_fft)
plt.show()

【讨论】:

  • 谢谢;我正在寻找fftshift,但找不到。
  • 为什么有 sqrt(2N)?
  • @omehoque:有 many different conventions 用于定义 DFT。它们在常数之前都是相同的。不同的群体(例如工程师、物理学家、数学家)倾向于支持不同的约定。上面使用的那个受到数学家的青睐,因为它使 DFT 和逆 DFT 公式对称。它使 Parseval 定理特别漂亮:(y**2).sum() 等于 (y_fft**2).sum()。它也是绘图的好选择,因为它使yy_fft 的大小大致相同。
  • NumPy 定义了 DFT this way。将该公式除以1/sqrt(N) 就是this answer 所称的单一缩放约定。上面之所以使用1/sqrt(2*N),是因为len(y)2*N,而不是N
  • 我发现了一个关于震级的相关问题:scicomp.stackexchange.com/q/11233/32010。有一个答案指出了采样频率(在本例中为 10./2/128)。但我不明白它来自哪里。
【解决方案2】:

你的结果甚至不接近高斯,甚至没有分成两半。

要获得您期望的结果,您必须将中心定位在索引 0 处的高斯分布,结果也将以这种方式定位。试试下面的代码:

from pylab import *
N = 128
x = r_[arange(0, 5, 5./N), arange(-5, 0, 5./N)]
y = exp(-x*x)
y_fft = fft(y) / sqrt(2 * N)
plot(r_[y[N:], y[:N]])
plot(r_[y_fft[N:], y_fft[:N]])
show()

绘图命令将数组分成两半并交换它们以获得更好的图片。

【讨论】:

  • 我是否必须将数组分成两半,然后...对于我尝试进行 FFT 的每个信号?还是这只适用于高斯函数,如果是,为什么?
  • @chutsu:我不知道你想做什么。只要您不关心高斯 FFT 的图是什么样子,将原点放在哪里可能并不重要。
【解决方案3】:

它以中心(即平均值)在系数索引零处显示。这就是为什么看起来右半边在左边,反之亦然。

编辑:探索以下代码:

import scipy
import scipy.signal as sig
import pylab
x = sig.gaussian(2048, 10)
X = scipy.absolute(scipy.fft(x))
pylab.plot(x)
pylab.plot(X)
pylab.plot(X[range(1024, 2048)+range(0, 1024)])

最后一行将从向量的中心开始绘制X,然后环绕到开头。

【讨论】:

  • 那么我将如何更改上述内容以纠正此问题?这只会影响高斯函数吗?其他波/信号呢?对不起,如果我的数学不是那么好......
【解决方案4】:

傅立叶变换隐含无限重复,因为它是一个信号的变换隐含无限重复。请注意,当您传递 y 进行转换时,不会提供 x 值,因此实际上转换的高斯是以 0 到 256 之间的中值为中心的高斯,即 128。

还要记住 f(x) 的平移是 F(x) 的相变。

【讨论】:

    【解决方案5】:

    根据 Sven Marnach 的回答,一个更简单的版本是这样的:

    from pylab import *
    N = 128
    
    x = ifftshift(arange(-5,5,5./N))
    
    y = exp(-x*x)
    y_fft = fft(y) / sqrt(2 * N)
    
    plot(fftshift(y))
    plot(fftshift(y_fft))
    
    show()
    

    这会产生与上述相同的图。

    关键(这对我来说似乎很奇怪)是 NumPy 假定的数据排序 --- 在 频率和 时域中 --- 是具有“零”值第一。这不是我对其他 FFT 实现的期望,例如 C 中的 FFTW3 库。

    这在上面的 unutbu 和 Steve Tjoa 的答案中略有捏造,因为他们在绘制 FFT 之前取其绝对值,从而消除了由于未及时使用“标准顺序”而导致的相位问题。

    【讨论】:

    • 我知道这篇文章已有 8 年历史,但这个答案是我找到的唯一可接受的答案。其他每个人都通过取绝对值来扫除相移问题,通常甚至在公认的答案中(例如在这篇文章中)。另请参阅此处:stackoverflow.com/questions/56154992/…scicomp.stackexchange.com/questions/11233/…,以及更多不适合评论的内容。谢谢你没有回避这个问题。取绝对值是完全错误的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-19
    • 2015-12-17
    • 2017-11-13
    相关资源
    最近更新 更多