3

我想使用 GPU 加速算法来执行快速且节省内存的 dft。但是,当我执行 时gpu::dft,目标矩阵会按照文档中的说明进行缩放。如何通过将宽度缩放到 来避免这个问题dft_size.width / 2 + 1?另外,为什么会这样缩放?我的 DFT 代码是这样的:

cv::gpu::GpuMat d_in, d_out;
d_in = in;
d_out.create(d_in.size(), CV_32FC2 );
cv::gpu::dft( d_in, d_out, d_in.Size );

其中in是一个CV_32FC1矩阵,即 512x512。

最好的解决方案是具有 sized_in.size和 type的目标矩阵CV_32FC2

4

2 回答 2

4

这是由于FFT 的输出中存在复杂的共轭对称性。Intel IPP对这种包装有很好的描述(OpenCV 使用相同的包装)。OpenCV dft函数也描述了这种封装。

因此,从gpu::dft文档中我们得到:

如果源矩阵是复数且输出未指定为实数,则目标矩阵是复数并且具有 dft_size 大小和 CV_32FC2 类型。

gpu::dft因此,如果您不希望将其打包,请确保将复杂矩阵传递给函数。您需要将第二个通道设置为全零:

Mat realData;

// ... get your real data...

Mat cplxData = Mat::zeros(realData.size(), realData.type());

vector<Mat> channels;
channels.push_back(realData);
channels.push_back(cplxData);

Mat fftInput;
merge(channels, fftInput);

GpuMat fftGpu(fftInput.size(), fftInput.type());
fftGpu.upload(fftInput);

// do the gpu::dft here...

不过有一个警告……使用 CCS 打包数据时,性能会提高 30-40%,因此使用全复杂输出会损失一些性能。

希望有帮助!

于 2011-12-19T15:09:51.713 回答
0

进行缩放以获得范围内的结果+/- 1.0。对于大多数需要处理数据频率表示的应用程序来说,这是最有用的形式。要检索未缩放的结果,请不要启用该DFT_SCALE标志。

编辑

结果的宽度被缩放,因为它是对称的。所以你所要做的就是以对称的方式附加以前的值。

频谱是对称的,因为在宽度的一半处满足采样定理。例如,采样率为 48 kHz 的信号源的 2048 点 DFT 只能表示高达 24 kHz 的值,并且该值表示为宽度的一半。

另请参阅Spectrum Analysis Using the Discrete Fourier Transform以供参考。

于 2011-12-19T14:37:41.793 回答