Reputation: 784
I created an application in Qt, which allow me to open image and use 2D FFT transform with FFTW library. The problem is that I can not retrieve proper pixel values with backward transformation. But let's start from begining.
This is how looks my FFTW function which I use
void FFTInterface::FFTW(int rows, int cols, QColor **imageInput,fftw_complex * in, fftw_complex * out)
{
fftw_plan g;
g = fftw_plan_dft_2d(rows, cols, in, out, FFTW_FORWARD, FFTW_MEASURE);
int k = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
in[k][0] = imageInput[i][j].red();
in[k][1] = 0.0;
k++;
}
}
fftw_execute(g);
fftw_destroy_plan(g);
}
rows, cols are size of an image, imageInput is the array of QColor, which keep the pixels value (in greyscale), in and out are object of fftw_complex, input and output arrays.
This function give me some result, which has to be show. To do this, I made some kind of scalling. Firstly, I use abs() function on every value, to be sure that it has positive value. After that, I scale the result.
void FFTInterface::Abs(fftw_complex *out, int rows, int cols)
{
int k = 0;
for(int i = 0; i < rows; i++){
for(int j = 0; j<cols; j++){
out[k][0] = abs(out[k][0]);
out[k][1] = abs(out[k][1]);
k++;
}
}
}
void FFTInterface::Scale(fftw_complex * in,int rows, int cols)
{
float c = 255.0 / log(1+Max(in,rows,cols));
int k = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
in[k][0] = c*log(1+in[k][0]);
in[k][1] = c*log(1+in[k][0]);
k++;
}
}
}
This process give me something that I need. Image looks ok. But I have problem to revert image to it's original. Function for BACKWARD is like below
void FFTInterface::IFFTW(int rows, int cols, fftw_complex * in, fftw_complex * out)
{
fftw_plan g;
g = fftw_plan_dft_2d(rows, cols, in, out, FFTW_BACKWARD, FFTW_MEASURE);
int k = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
in[k][1] = 0.0;
k++;
}
}
fftw_execute(g);
fftw_destroy_plan(g);
}
I found somewhere that it's not normalized (the results are VERY BIG). To normalize I just divide values by N (256,512 etc.) - width or height of the image (it's always a square), but the values are different then the original ones.
Do you have any idea where I'm missing something? Scalling? I should maybe use other fft method from library? I have stucked.
Upvotes: 1
Views: 645
Reputation: 14579
By taking the absolute value and scaling the complex components for the purpose of displaying the image you are modifying the data in such a way that the inverse transform no longer gives you the original input. To avoid this problem I would suggest you create a copy of the data you wish to display before you scale it. Also, make sure not to forget that the input to the inverse transform should be the output from the forward transform (or the last output in a signal processing chain as may be).
In pseudo-code you could do this like so:
interface.FFTW(rows, cols, imageInput, in, out);
size_t N = rows*cols;
fftw_complex* todisplay = fftw_malloc(N);
std::copy(out, out+N, todisplay);
interface.Abs(todisplay);
interface.Scale(todisplay);
... display "todisplay" on your Qt user interface
fftw_free(todislay);
interface.IFFTW(rows, cols, out, reconstructed);
Upvotes: 2