Displaying Fourier transforms in OpenCV




I'm just learning to use OpenCV and am having a problem with using DFT. I've done a signal processing class which used MatLab, so I'm trying to go through some of the exercises we did in that class. I'm trying to get and display the FT of an image, so I can mask some of the frequencies. I'd like to be able to see the FT, so I know how big to make the mask, but when I tried, I got an image like this:

rather than like one of these
alt text http://www.ceremade.dauphine.fr/~peyre/numerical-tour/tours/graphics_synthesis_fourier/index_03.png
Am I forgetting a step somewhere? I'm loading the image, converting its type to CV_32FC1, getting the matrix of it, getting the DFT, and then getting turning the resulting matrix back into an image. I'll post the code I'm using if it will be of any help?
Or if someone has a link to an example of displaying the FT? I could only find ones which used it for the convolution.

EDIT: Did I get the Phase of the image?

matlab   image-processing   opencv   fft  
  edited Jun 5 '10 at 10:22  asked Jun 5 '10 at 10:14   Simonw  487 4 10 26      Certainly it is not the phase of the input image. Since your image is only black and white -- when it should have a range of gray values -- my guess is that you are having some error in conversion. –    Alceu Costa  Jun 13 '10 at 23:13

 | 

Answers
1

I have run into similar trouble in trying to visualize the magnitude of a 2D DFT on an image with respect to OpenCV. I finally churned out a working implementation. I wouldn't consider it great code, and it has only been tested on a 256 x 256 8-bit (gray-scale) single-channel image--lenna.png (it may need to be tweaked to appropriately pad for other image dimensions). The mean-squared error between the input image and the reconstructed image is zero, so it is working as it should. OpenCV v2.1 is required.

file: mstrInclude.h

    #ifndef _MASTER_INCLUDE_
    #define _MASTER_INCLUDE_

    // Standard
    #include <stdio.h>
    #include <string>
    #include <sstream>
    #include <iostream>
    #include <cmath>
    using namespace std;

    // OpenCV2.1
    #include "cv.h"
    #include "highgui.h"
    using namespace cv;

    #define LOAD_IMAGE "lenna.png"

    #endif // _MASTER_INCLUDE_

file: main.cpp

    #include "mstrInclude.h"
    void translateImg(Mat& imgIn, Mat& imgOut)
    {
        int i, j;

        for (i = 0; i < imgIn.rows; i++)
            for (j = 0; j < imgIn.cols; j++)
                imgOut.at<double>(i,j) = imgIn.at<double>(i,j) * pow(-1.0, i+j);
    }
    void scaleImg(Mat& imgIn, Mat& imgOut, float scaleFactor)
    {
        int i, j;

        for (i = 0; i < imgIn.rows; i++)
            for (j = 0; j < imgIn.cols; j++)
                imgOut.at<double>(i,j) = (double)scaleFactor * log(1.0 + imgIn.at<double>(i,j));
    }

    void consoleOut(cv::Mat outMat, int rows = 5, int cols = 5)
    {
        rows = ((rows == -1 || rows >= outMat.rows) ? outMat.rows : rows);
        cols = ((cols == -1 || cols >= outMat.cols) ? outMat.cols : cols);

        for(int i = 0; i < rows; i++)
        {
            for(int j = 0; j < cols; j++)
            {
                cout << outMat.at<double>(i, j);
                cout << " ";
            }
            cout << endl;
        }
    }

    double calcMSE(Mat& imgOrig, Mat& imgReconst)
    {
        int valOrig = 0, valReconst = 0;
        double MSE = 0.0;

        for(int i = 0; i < imgOrig.rows; i++)
        {
            for (int j = 0; j < imgOrig.cols; j++)
            {
                valOrig = imgOrig.at<unsigned char>(i, j);
                valReconst = imgReconst.at<unsigned char>(i, j);

                MSE += pow( (double)(valOrig - valReconst), 2.0 );
            }
        }
        return (MSE / (imgOrig.rows * imgOrig.cols));
    }

    string convertInt(int number) // converts integer to string
    {
       stringstream ss;
       ss << number;
       return ss.str();
    }

    int main(unsigned int argc, char* const argv[])
    {
        int dftH, dftW;
        cv::Mat imgIn;

        imgIn = cv::imread(LOAD_IMAGE, 0); //grayscale
        cv::imshow("Original Image", imgIn);
        waitKey();

        dftH = cv::getOptimalDFTSize(imgIn.rows);
        dftW = cv::getOptimalDFTSize(imgIn.cols);

        Mat imgMod;
        Mat imgPrecFFT(dftH, dftW, CV_64FC1, Scalar::all(0));
        imgIn.convertTo(imgMod, CV_64FC1);
        imgPrecFFT = imgMod(cv::Range::all(), cv::Range::all()).clone();

        // translate image
        std::vector<Mat> imgsTrans;
        imgsTrans.push_back(Mat_<double>(imgIn.size(), CV_64FC1));
        imgsTrans.push_back(Mat_<double>(imgIn.size(), CV_64FC1));
        imgsTrans[1].setTo(Scalar::all(0), Mat());
        translateImg(imgPrecFFT, imgsTrans[0]);

        Mat imgPrecTransFFT(imgIn.size(), CV_64FC2, Scalar::all(0));
        cv::merge(imgsTrans, imgPrecTransFFT);

        // dft
        cv::Mat imgFFT;
        dft(imgPrecTransFFT, imgFFT, DFT_COMPLEX_OUTPUT);
        cv::Mat imgDispFFT;

        // calculate magnitude
        Mat imgMagnitude(imgIn.size(), CV_64FC1);
        std::vector<Mat> chans;
        cv::split(imgFFT, chans);
        cv::magnitude(chans[0], chans[1], imgMagnitude);

        // scale magnitude image
        Mat imgMagnitudeScaled(imgIn.size(), CV_64FC1);
        scaleImg(imgMagnitude, imgMagnitudeScaled, 10.0);

        // display magnitude image
        cv::Mat imgDisp;
        cv::convertScaleAbs(imgMagnitudeScaled, imgDisp);
        imshow("Magnitude Output", imgDisp);
        waitKey();

        // inverse dft
        cv::split(imgFFT, chans);
        chans[1].zeros(imgIn.size(), CV_64FC1);
        cv::merge(chans, imgFFT);
        cv::Mat invFFT;
        cv::idft(imgFFT, invFFT, DFT_REAL_OUTPUT + DFT_SCALE);

        // translate image back to original location
        cv::split(invFFT, imgsTrans);
        Mat imgAfterTrans(imgIn.size(), CV_64FC1);
        translateImg(imgsTrans[0], imgAfterTrans);
        imgAfterTrans.convertTo(imgDisp, CV_8UC1);

        imshow("After Inverse Output", imgDisp);
        waitKey();

        // calculate and output mean-squared error between input/output images
        double MSE = calcMSE(imgIn, imgDisp);
        cout<<endl<<"MSE: "<<MSE<<endl;
        waitKey();

        return 0;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值