用OpenCV在c++中执行gpu::dft缩放

Scaling performed by gpu::dft with OpenCV in C++

本文关键字:gpu dft 缩放 执行 OpenCV c++      更新时间:2023-10-16

我想使用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 );

其中inCV_32FC1矩阵,为512x512。

最佳解决方案是目标矩阵,其大小为d_in.size,类型为CV_32FC2

这是由于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%的性能提升,所以你会因为使用全复杂输出而损失一些性能。

希望有帮助!

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

编辑

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

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

也可以参考一下使用离散傅里叶变换的频谱分析