通过 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) 缩放正向和反向变换,因此在使用傅里叶变换时检查文档(或编写快速测试代码)通常很有用。
我正在玩一些玩具代码,以尝试验证我是否了解离散傅里叶变换在 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) 缩放正向和反向变换,因此在使用傅里叶变换时检查文档(或编写快速测试代码)通常很有用。