通过 cv::dft() 和 cv::DFT_INVERSE 的往返导致 1d 样本的幅度加倍

Round trip through cv::dft() and cv::DFT_INVERSE leads to doubling magnitude of 1d samples

我正在玩一些玩具代码,以尝试验证我是否了解离散傅里叶变换在 OpenCV 中的工作原理。我发现了一个相当令人费解的案例,我相信原因是我调用 cv::dft() 时使用的标志不正确。

我从实值(例如音频)样本的一维数组开始。 (作为列存储在 cv::Mat 中。)

我使用 cv::dft() 来获取傅立叶桶的复值数组。

我使用 cv::dft() 和 cv::DFT_INVERSE 将其转换回来。

我多次这样做,打印结果。结果似乎是正确的形状,但大小不正确。

代码:

cv::Mat samples(1, 2, CV_64F);
samples.at<double>(0, 0) = -1;
samples.at<double>(0, 1) = 1;
std::cout << "samples(" << samples.type() << "):" << samples << std::endl;
for (int i = 0; i < 3; ++i) {
  cv::Mat buckets;
  cv::dft(samples, buckets, cv::DFT_COMPLEX_OUTPUT);
  samples = cv::Mat();
  cv::dft(buckets, samples,
          cv::DFT_INVERSE | cv::DFT_COMPLEX_INPUT | cv::DFT_REAL_OUTPUT);

  std::cout << "buckets(" << buckets.type() << "):" << buckets << std::endl;
  std::cout << "samples(" << samples.type() << "):" << samples << std::endl;
}

输出:

samples(6):[-1, 1]
buckets(14):[0, 0, -2, 0]
samples(6):[-2, 2]
buckets(14):[0, 0, -4, 0]
samples(6):[-4, 4]
buckets(14):[0, 0, -8, 0]
samples(6):[-8, 8]

我原以为上面的输出会重复。例如。 [-1, 1], [0, 0, -1, 0], .... 相反,幅度在每次往返时加倍。

我的理解有误吗?还是我使用了错误的标志?等等

默认情况下,opencv 中的逆向 DFT 不会对结果进行缩放,因此您得到的是输入乘以数组的长度。 这是一种常见的优化,因为并不总是需要缩放,并且最有效的逆向 DFT 算法只使用不产生缩放的正向 DFT。 您可以通过向逆 DFT 添加 cv::DFT_SCALE 标志来解决此问题。

一些库使用 1/sqrt(N) 缩放正向和反向变换,因此在使用傅里叶变换时检查文档(或编写快速测试代码)通常很有用。