2011-12-19 55 views
2

我想使用GPU加速算法来执行快速和节省内存的dft。但是,当我执行gpu::dft时,目标矩阵按照documentation中的解释进行缩放。如何通过将宽度缩放到dft_size.width/2 + 1来避免此问题?另外,它为什么这样缩放?我对DFT代码是这样的:在C++中使用OpenCV执行gpu :: 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矩阵,这是512×512。

最好的解决方案是大小为d_in.size和类型CV_32FC2的目标矩阵。

回答

4

这是由于存在于FFT输出中的complex conjugate对称性造成的。英特尔IPP具有此包装的good description(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... 

有一个警告,但...你约30-40%的性能提升,在使用CCS打包数据,因此你将失去某些性能使用全复合输出。

希望有帮助!

+0

非常感谢您的解释。这工作!如果有一天我会有非常大的图片,我会换成CCS打包数据格式。也感谢链接。 – Sonic 2011-12-19 15:27:31

+0

没问题!很高兴帮助:) – mevatron 2011-12-19 16:29:28

+0

我只想补充一点,与非gpu dft函数不同,OpenCV的'gpu :: dft'不使用Intel的CCS格式。相反,它使用cuFFT的打包格式。不同之处在于CCS是与真实图像具有相同尺寸的单通道图像,并且cuFFT是宽度约为一半的双通道图像。 – may5694 2014-07-17 15:46:39

0

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

编辑

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

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

同样供参考请看Spectrum Analysis Using the Discrete Fourier Transform

+0

我不是说dft结果值的缩放。我的意思是结果宽度的缩放。 – Sonic 2011-12-19 14:47:15

+0

啊,现在我明白了。做了一个编辑。 – 2011-12-19 14:55:10

+0

是的......有我的问题:想象我有一个8x8矩阵,我会改变它。我的结果是5x8而不是4x8。这意味着,有列,我不必镜像。 – Sonic 2011-12-19 15:12:44