在 OpenCV 中显示傅里叶变换

发布于 2024-09-04 07:15:39 字数 639 浏览 0 评论 0原文

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

编辑:我得到图像的相位了吗?

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:
alt text
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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

§普罗旺斯的薰衣草 2024-09-11 07:15:39

我在尝试使用 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;
    }

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;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文