【问题标题】:Why does my 2D IDFT produce double the expected amplitudes? (FFTW)为什么我的 2D IDFT 会产生两倍的预期幅度? (FFTW)
【发布时间】:2020-09-25 12:30:32
【问题描述】:

我正在使用复数到实数的 2D IDFT 将复数信号可视化为图像。我通过手动设置模式来初始化复杂的频域。但是,某些模式产生的实际输出似乎是预期的两倍。

我的代码:

int N = 8;
int logical_width = N / 2 + 1; // Logical width of frequency domain data

double* T = new double[N * N];
fftw_complex* F = (fftw_complex*)fftw_alloc_complex(N * logical_width);

fftw_plan plan = fftw_plan_dft_c2r_2d(N, N, F, T, FFTW_MEASURE);

// Initialize all frequency modes to 0
for (int i = 0; i < N * logical_width; i++) {
    F[i][REAL] = 0.0;
    F[i][IMAG] = 0.0;
}

F[1][REAL] = 16.0; // Set mode k[0, 1]

fftw_execute(plan);

printTime(T, N); // Print time domain to console

printTime()的输出:

IDFT 后信号的幅度似乎为 32。但是,我希望它是 16,因为唯一的贡献模式是 k[0, 1] = 16 + 0i

为什么会这样?我应该在执行 IDFT 之前以某种方式转换信号吗?

【问题讨论】:

  • 我不确定printTime() 是如何计算幅度的,但考虑到函数a * sin(x) 产生的值介于-aa 之间,所以最大值和最小值之间的差是@987654331 @.
  • printTime() 不计算任何东西。它只打印四舍五入到小数点后 2 位的时域值。在这种情况下,最大值和最小值是 32 和 -32,即使输入的格式为 16.0 * cos(x)
  • 在进行 fft 时,通常需要进行重新缩放或标准化。我以为是N。所以我不太了解一些事情。看看thisfftw 文档

标签: c++ fftw dft


【解决方案1】:

您正在应用 C2R 转换。正如我在my answer to your previous question 中解释的那样,它需要一个共轭对称输入。您提供一半输入,另一半假定为输入的共轭对称。因此,您设置了两种模式,而不是一种,每种模式的幅度为 16。它们一起形成幅度为 32 的正弦曲线。

请注意,FFTW 的逆 DFT 不会归一化。 DFT有不同的定义,有的将归一化放在正变换中,有的将归一化放在逆变换中。 FFTW 根本没有标准化。这导致 IFFT(FFT(f)) = Nf(N 为样本数)。您需要在某处手动规范化以保持等式。最常见的逆变换是归一化的。在您的情况下,这将导致幅度为 32/N 的正弦曲线,这就是您在大多数信号处理教科书中会看到的。例如,参见this PDF 中的第 7 页。

【讨论】:

  • 嗨,克里斯,再次感谢您的回复。我注意到对于某些模式,这种幅度的加倍并没有发生。我认为是这种情况,因为它们在频域中没有共轭?由于我意识到我的解释可能有点差,我将其可视化:i.imgur.com/JJPdf67.png 时域是 n0 x n1。灰色单元格是冗余的,不是由 FFTW 计算的。红细胞在时域中没有共轭。对吗?
  • @Naemesis 是的,没错。可以说,红细胞是它们自己的共轭物,因此有望得到真正的重视。顺便说一句,对于奇数大小的变换,您只有一个这样的列。
  • 嗨 Cris,很抱歉再次打扰您,但我一直在为另一个与复杂 DFT 相关的问题苦苦挣扎。你介意看看吗? stackoverflow.com/q/64155448/4017363
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-05
  • 1970-01-01
  • 2021-02-01
  • 2014-03-26
  • 2016-03-29
  • 2020-09-23
  • 2019-02-03
相关资源
最近更新 更多