C / C ++中固定长度实数输入数据的高效2D FFT

时间:2012-12-04 12:16:00

标签: c++ optimization opencv fft fftw

我正在开发一种算法,可以多次调用FFT函数。我有几个时间限制(实时需要)所以我需要最小化每次FFT调用所花费的时间。

我正在使用OpenCV库,我已经用两种不同的方法实现了我的代码:

  • 使用FFTW库。数据/存储器管理+ FFT(8ms)= 14ms(均值,FFT_MEASURE标志)。
  • 使用OpenCV fft功能。数据/存储器管理+ FFT(21ms)= 23ms(均值)。

由于我的输入数据总是固定为512x512像素的真实图像,您认为如果我自己实现基于DFT的数学定义的FFT算法,存储正弦/余弦表可以实现更好的性能还是FFTW库真的非常优化?有更好的想法吗?

我们将非常感谢所有的想法和建议。到目前为止,我不考虑并行化或GPU实现。

谢谢

更新

系统:Windows 7中的Intel Xeon 5130 2.0GHz CPU,Visual Studio 10.0和FFTW 3.3.3(按照网站上的说明编译),OpenCV 2.4.3。

使用FFTW进行FFT调用的代码示例(输入:OpenCV Mat CV_32F(1通道,浮点型),输出OpenCV Mat CV_32FC2(2通道,浮点型):

float           *im_data;

fftwf_complex    *data_in;
fftwf_complex    *fft;      

fftwf_plan       plan_f;

int             i, j, k;

int height=I.rows;
int width=I.cols;
int N=height*width;


float* outdata = new float[2*N];
im_data = ( float* ) I.data;

data_in = ( fftwf_complex* )fftwf_malloc( sizeof( fftwf_complex ) * N );
fft     = ( fftwf_complex* )fftwf_malloc( sizeof( fftwf_complex ) * N );

plan_f = fftwf_plan_dft_2d( height , width , data_in , fft ,  FFTW_FORWARD ,  FFTW_MEASURE );

for(int i = 0,k=0; i < height; ++i) {
    float* row = I.ptr<float>(i);
    for(int j = 0; j < width; j++) {
        data_in[k][0]=(float)row[j];
        data_in[k][1] =(float)0.0;
        k++;
    }
} 

fftwf_execute( plan_f );

int width2=2*width;
// writing output matrix: RealFFT[0],ImaginaryFFT[0],RealFFT[1],ImaginaryFFT[1],...
for( i = 0, k = 0 ; i < height ; i++ ) {
    for( j = 0 ; j < width2 ; j++ ) {

        outdata[i * width2 + j] = ( float )fft[k][0];
        outdata[i * width2 + j+1] = ( float )fft[k][1];
        j++;
        k++;
    }
}

Mat fft_I(height,width,CV_32FC2,outdata);

fftwf_destroy_plan( plan_f );
fftwf_free( data_in );
fftwf_free( fft );


return fft_I;

3 个答案:

答案 0 :(得分:3)

您使用FFTW的FFT时间似乎非常高。为了充分利用固定大小FFT的FFTW,您应该使用FFTW_PATIENT标志生成计划,然后理想地保存生成的“智慧”以供后续重复使用。您可以使用自己的代码或使用fftw-wisdom工具生成智慧。

答案 1 :(得分:1)

Intel Math Kernel Library(与英特尔编译器分开)的FFT在大多数情况下比FFTW快。我不知道你的情况是否足以改善价格。

我同意其他人说滚动你自己的FFT可能不是很好地利用你的时间(除非你想学习如何去做)。多年来,可用的FFT实现(FFTW,MKL)已经过如此精细的调整。我并不是说你不能做得更好,但可能会有很多工作和时间来获得边际收益。

答案 2 :(得分:0)

相信我fftw真的非常优化,机会非常小,你可以做得更好。

您用于编译fftw的编译器是什么?有时,英特尔的编译器提供比gcc更好的性能