1

我只是在学习使用 OpenCV,但在使用 DFT 时遇到了问题。我已经完成了一个使用 MatLab 的信号处理课程,所以我正在尝试完成我们在该课程中所做的一些练习。我正在尝试获取并显示图像的 FT,因此我可以掩盖一些频率。我希望能够看到 FT,所以我知道要制作多大的面具,但是当我尝试时,我得到了这样的图像:
替代文字
而不是像其中一个
替代文本 http://www.ceremade。 dauphine.fr/~peyre/numerical-tour/tours/graphics_synthesis_fourier/index_03.png
我是不是忘记了某个步骤?我正在加载图像,将其类型转换为 CV_32FC1,获取它的矩阵,获取 DFT,然后将生成的矩阵转换回图像。我会发布我的代码
或者,如果有人有显示 FT 示例的链接?我只能找到将它用于卷积的那些。

编辑:我得到图像的阶段了吗?

4

1 回答 1

2

在尝试可视化图像上相对于 OpenCV 的 2D DFT 的幅度时,我遇到了类似的麻烦。我终于制定了一个可行的实现。我不会认为它是很好的代码,它只在 256 x 256 8 位(灰度)单通道图像上进行了测试——lenna.png(它可能需要调整以适当地填充其他图像方面)。输入图像和重建图像之间的均方误差为零,因此它可以正常工作。需要 OpenCV v2.1。

文件: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_

文件: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;
    }
于 2010-12-24T10:02:57.327 回答