gui
gui

Reputation: 425

FFTW and OpenCV's C++ interface, real and imaginary part in Mat output

I'm trying to code a FFT/IFFT function with FFTW 3.3 and OpenCV 2.1 using the C++ interface. I've seen a lot of examples using the old OpenCV formats and I did a direct conversion, but something doesn't work.

The objective of my function is to return a Mat object with the real part and the imaginary part of the FFT, like dft default OpenCV function does. Here is the code of the function. Program gets blocked with memory problem in the lines that copy im_data to data_in.

Does somebody know what am I doing wrong? Thank you

Mat fft_sr(Mat& I)
{

double          *im_data;
double          *realP_data;
double          *imP_data;

fftw_complex    *data_in;
fftw_complex    *fft;      

fftw_plan       plan_f;

int width     = I.cols;
int height    = I.rows;
int step      = I.step;

int             i, j, k;

Mat realP=Mat::zeros(height,width,CV_64F); // Real Part FFT
Mat imP=Mat::zeros(height,width,CV_64F); // Imaginary Part FFT


im_data = ( double* ) I.data;
realP_data = ( double* ) realP.data;
imP_data = ( double* ) imP.data;


data_in = ( fftw_complex* )fftw_malloc( sizeof( fftw_complex ) * width * height );
fft     = ( fftw_complex* )fftw_malloc( sizeof( fftw_complex ) * width * height );

// Problem Here
for( i = 0, k = 0 ; i < height ; i++ ) {
    for( j = 0 ; j < width ; j++ ) {
        data_in[k][0] = ( double )im_data[i * step + j];
        data_in[k][1] = ( double )0.0;
        k++;
    }
}


plan_f = fftw_plan_dft_2d( height, width, data_in, fft,  FFTW_FORWARD,  FFTW_ESTIMATE );


fftw_execute( plan_f );

// Copy real and imaginary data
for( i = 0, k = 0 ; i < height ; i++ ) {
    for( j = 0 ; j < width ; j++ ) {
        realP_data[i * step + j] = ( double )fft[k][0];
        imP_data[i * step + j] = ( double )fft[k][1];
        k++;

    }
}



Mat fft_I(I.size(),CV_64FC2);
Mat fftplanes[] = {Mat_<double>(realP), Mat_<double>(imP)};
merge(fftplanes, 2, fft_I);

fftw_destroy_plan(plan_f);
fftw_free(data_in);
fftw_free(fft);
return fft_I;   
}

Upvotes: 1

Views: 2186

Answers (3)

Driver
Driver

Reputation: 13

Statement

im_data = ( double* ) I.data;

defines im_data as double pointer to image data. I think that should be mandatory that I was a double values image.

Upvotes: 0

Dima Maligin
Dima Maligin

Reputation: 1492

I know this is old but when you are using fftw you need to initialize fftw_complex *data_in only after creating the plan for the fft, if i recall correctly when you create the plan it sets all the *data_in values to 0. so allocate before the plan and initialize after!

Upvotes: 0

Good Night Nerd Pride
Good Night Nerd Pride

Reputation: 8490

You are using step wrong. It is meant to index into Mat::data. Since you already casted Mat::data to double* when assigning it to im_data, you can index into im_data "normally":

data_in[k][0] = im_data[i * width + j];

When using step the correct way to index is:

data_in[k][0] = ( double )I.data[i * step + j];

Update:

Try to access your images row-wise. That way you avoid running into problems with stride/step, while still exploiting fast access:

for (int i = 0; i < I.rows; i++)
{
    double* row = I.ptr<double>(i);

    for (int j = 0; j < I.cols; j++)
    {
        // Do something with the current pixel.
        double someValue = row[j];
    }
}

Upvotes: 3

Related Questions