1

we've compiled the KissFFT library and it appears to be running fine, but we're not sure how we use it to get the frequency domain of a 2d image. Any help would be fantastic.

PS. We're running it in the After Effects SDK.

Timbucktato
  • 117
  • 9
  • `KissFFT` is `C` (`not C++`). I've used the library for audio analysis but I know that it can't handle 3d images directly. Have a look at https://github.com/mborgerding/kissfft/blob/master/tools/kiss_fftnd.c. Also, note that you either have to reduce your image to a greyscale one or handle all pixel channels independently (R,G,B need to be processed separately) – dsp_user Jan 21 '19 at 07:15
  • Hey @dsp_user, Thanks for replying, i'm aware it's C and not C++ however once it's compiled into a library it can be run by a C++ program. Our images are 2 dimensional not 3 and i'm aware of the limitations of grey scale, we plan to run each channel individually. I've looked at that link however i'm still not sure how to actually get the result correctly. – Timbucktato Jan 21 '19 at 07:23
  • KissFFT comes with a function that computes a multi-dimensional FFT: `kiss_fftnd `, it's implemented here: https://sourceforge.net/p/kissfft/code/ci/default/tree/tools/kiss_fftnd.c – Cris Luengo Jan 21 '19 at 08:21

1 Answers1

2

I haven't used KissFFT with images (only with audio) but here's my attempt based on what I've read in the docs. You should create 3 arrays for the individual colour components (i.e. create img1/img2/img3).

 //(I can't test this code now because I don't have kiss_fft)

 kiss_fft_scalar img1[M][N]; //array containing red pixels 
 kiss_fft_scalar img2[M][N]; //array containing green pixels
 kiss_fft_scalar img3[M][N];//array containing blue pixels


int mDim[2] = { N, M }; 
const int numDim = 2; //number of dimensions

kiss_fft_cpx *cinRed =  new kiss_fft_cpx[N * M]; 
kiss_fft_cpx *coutRed = new kiss_fft_cpx[N * M];
kiss_fft_cpx *cinGreen =  new kiss_fft_cpx[N * M]; 
kiss_fft_cpx *coutGreen = new kiss_fft_cpx[N * M];
kiss_fft_cpx *cinBlue =  new kiss_fft_cpx[N * M]; 
kiss_fft_cpx *coutBlue = new kiss_fft_cpx[N * M];

kiss_fftnd_cfg state = kiss_fftnd_alloc (mDim, numDim, 0, 0, 0);

int k=0;
for (int i=0;i<M;++i) {
    for(int j=0;j<N;j++){
        cinRed[k].r = img1[i][j];
        cinRed[k].i = 0; 
        cinGreen[k].r = img2[i][j];
        cinGreen[k].i = 0; 
        cinBlue[k].r = img3[i][j];
        cinBlue[k].i = 0; 

        k++;
    }
}

kiss_fftnd(state,cinRed,coutRed);//coutRed contains 2D fft results for img1 (red channel)
kiss_fftnd(state,cinGreen,coutGreen);
kiss_fftnd(state,cinBlue,coutBlue);

//for inverse 2D FFT just use
state = kiss_fftnd_alloc (mDim, numDim, 1, 0, 0);//1 sets inverse to true

kiss_fftnd(state,coutRed,cinRed); //note that cin and cout have switched positions
kiss_fftnd(state,coutGreen,cinGreen);
kiss_fftnd(state,coutRed,cinGreen);

Thank you Cris for letting me know that I should use kiss_fftnd (I've deleted the old code and procedure)

dsp_user
  • 2,061
  • 2
  • 16
  • 23
  • @Cris, If I'm not mistaken, the process of computing a `2D FFT` can be reduced to computing a `1D FFT` for all the rows. I'll try to find a link somewhere. – dsp_user Jan 21 '19 at 14:03
  • 1
    No, you need to compute 1D FFT on all rows, then on the result, compute the 1D FFT on all columns. This is what the `kiss_fftnd` that I linked does. No need to implement this by hand. There is also a real version of that function. – Cris Luengo Jan 21 '19 at 14:08