4

I have created dft of an image and after some adjustment with filters i want to convert it back to the real image but every time when i do that it gives me wrong result ..seems like its not converting it back. ForierTransform and createGaussianHighPassFilter are my own functions rest of the code i am using like below for the inversion back to real image.

Mat fft = ForierTransform(HeightPadded,WidthPadded);
Mat ghpf = createGaussianHighPassFilter(Size(WidthPadded, HeightPadded), db);
Mat res;
cv::multiply(fft,ghpf,res);
imshow("fftXhighpass1", res);
idft(res,res,DFT_INVERSE,res.rows);
cv::Mat croped = res(cv::Rect(0, 0, img.cols,img.rows));

//res.convertTo(res,CV_32S);
imshow("fftXhighpass", res);

even if i dont apply the filter i am unable to reverse back dft result ... here is my dft code is , i could not find any sample to reverse dft back to normal image..

Mat ForierTransform(int M,int N)
{
    Mat img = imread("thumb1-small-test.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    Mat padded;
    copyMakeBorder(img, padded, 0, M - img.rows, 0, N - img.cols, BORDER_CONSTANT, Scalar::all(0));

    Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
    Mat complexImg;
    merge(planes, 2, complexImg);

    dft(complexImg, complexImg);


    split(complexImg, planes);
    magnitude(planes[0], planes[1], planes[0]);
    Mat mag = planes[0];
    mag += Scalar::all(1);
    log(mag, mag);

        // crop the spectrum, if it has an odd number of rows or columns
    mag = mag(Rect(0, 0, mag.cols & -2, mag.rows & -2));


    normalize(mag, mag, 0, 1, CV_MINMAX);
    return mag;
}

kindly help

[EDIT: After I found the solution with the help of mevatron] (below is the correct code)

 Mat ForierTransform(int M,int N)
{
    Mat img = imread("thumb1-small-test.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    Mat padded;
    copyMakeBorder(img, padded, 0, M - img.rows, 0, N - img.cols, BORDER_CONSTANT, Scalar::all(0));

    Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
    Mat complexImg;
    merge(planes, 2, complexImg);

    dft(complexImg, complexImg);

    return complexImg;
}

Mat img = imread("thumb1-small-test.jpg",CV_LOAD_IMAGE_GRAYSCALE);
int WidthPadded=0,HeightPadded=0;
WidthPadded=img.cols*2;
HeightPadded=img.rows*2;
int M = getOptimalDFTSize( img.rows );
//Create a Gaussian Highpass filter 5% the height of the Fourier transform
double db  = 0.05 * HeightPadded;


Mat fft = ForierTransform(HeightPadded,WidthPadded);
Mat ghpf = createGaussianHighPassFilter(Size(WidthPadded, HeightPadded), db);
Mat res;

cv::mulSpectrums(fft,ghpf,res,DFT_COMPLEX_OUTPUT);


idft(res,res,DFT_COMPLEX_OUTPUT,img.rows);

Mat padded;
copyMakeBorder(img, padded, 0, img.rows, 0, img.cols, BORDER_CONSTANT, Scalar::all(0));
Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
split(res, planes);
magnitude(planes[0], planes[1], planes[0]);
Mat mag = planes[0];
mag += Scalar::all(1);
log(mag, mag);

// crop the spectrum, if it has an odd number of rows or columns
mag = mag(Rect(0, 0, mag.cols & -2, mag.rows & -2));

int cx = mag.cols/2;
int cy = mag.rows/2;

normalize(mag, mag, 1, 0, CV_MINMAX);

cv::Mat croped = mag(cv::Rect(cx, cy, img.cols,img.rows));
cv::threshold(croped , croped , 0.56, 1, cv::THRESH_BINARY);

imshow("fftPLUShpf", mag);
imshow("cropedBinary", croped);

It now can able to display ridges valley of finger , and can be more optimize with respect to threshold as well

wolvorinePk
  • 1,760
  • 5
  • 36
  • 67
  • guys please help me out from this ....i have tried some tests by changing the code in ForierTransform function i have returned the planes element 1 like below. Doing this get me the real pic but it is very large faint and with very bad look.. I have just returned the Planes[1] instead of further below calculation of ForierTransform(int M,int N) function. e.g. after magnitude(planes[0], planes[1], planes[0]); return planes[1]; – wolvorinePk Mar 12 '12 at 11:08
  • on the conversion side i have added few more code idft(res,res,DFT_INVERSE + DFT_SCALE,img.rows); Mat padded; copyMakeBorder(img, padded, 0, img.rows, 0, img.cols, BORDER_CONSTANT, Scalar::all(0)); Mat planes[] = {Mat_(padded), Mat::zeros(padded.size(), CV_32F)}; split(res, planes); magnitude(planes[0], planes[1], planes[0]); Mat mag = planes[0]; mag += Scalar::all(1); log(mag, mag); mag = mag(Rect(0, 0, mag.cols & -2, mag.rows & -2)); normalize(mag, mag, 1, 0, CV_MINMAX); – wolvorinePk Mar 12 '12 at 11:11
  • the result comes like this http://oi40.tinypic.com/jshvdu.jpg kindly help me , i have spent several hours and still no success.... – wolvorinePk Mar 12 '12 at 11:13

1 Answers1

3

I see a few problems going on here.

First, you need to use the mulSpectrums function to convolve two FFTs, and not multiply.

Second, the createGaussianHighPassFilter is only outputting a single channel non-complex filter. You'll probably need to just set the complex channel to Mat::zeros like you did for your input image.

Third, don't convert the output of the FFT to log-magnitude spectrum. It will not combine correctly with the filter, and you won't get the same thing when performing the inverse. So, just return complexImg right after the DFT is executed. Log-magnitude spectrum is useful for a human to look at the data, but not for what you are trying to do.

Finally, make sure you pay attention to the difference to between the full-complex output of dft and the Complex Conjugate Symmetric (CCS) packed output. Intel has a good page on how this data is formatted here. In your case, for simplicity I would keep everything in full-complex mode to make your life easier.

Hope that helps!

mevatron
  • 13,911
  • 4
  • 55
  • 72
  • Thankssss a lot mevatron your experience is great ..i have followed your advice and i first changed the single channel filter function createGaussianHighPassFilter into multi channel using below code ..... normalize(ghpf, ghpf, 0, 1, CV_MINMAX); Mat padded; copyMakeBorder(ghpf, padded, 0, size.height - ghpf.rows, 0, size.width - ghpf.cols, BORDER_CONSTANT, Scalar::all(0)); Mat planes[] = {Mat_(padded), Mat::zeros(padded.size(), CV_32F)}; Mat complexImg; merge(planes, 2, complexImg); return complexImg; – wolvorinePk Mar 13 '12 at 10:43
  • after that i have used cv::mulSpectrums(fft,ghpf,res,DFT_COMPLEX_OUTPUT); idft(res,res,DFT_COMPLEX_OUTPUT,img.rows); On the result that came I have used threshold to see the edges of finger ... I have tried log and without log result for it and it gives same result in threshold for both... Once again thank you so much and kindly correct me if i have still done any mistake above or now i am good to go (just for the sake of optimization)... :) – wolvorinePk Mar 13 '12 at 10:47
  • Very cool :) For the sake of others interested, could you edit your question with the updated code? Glad to hear things are working out! – mevatron Mar 13 '12 at 16:38
  • The above link to Intels explanation of the Complex Conjugate Symmetric output format is broken. Here's a new one: [packed format explanation](https://software.intel.com/en-us/node/504243). – gebi Jul 01 '15 at 13:40