我想使用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。
最佳解决方案是目标矩阵,其大小为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的值,并且该值以宽度的一半表示。
也可以参考一下使用离散傅里叶变换的频谱分析