Отображение преобразований Фурье в OpenCV - PullRequest
1 голос
/ 05 июня 2010

Я только учусь использовать OpenCV и у меня проблема с использованием DFT. Я прошел класс обработки сигналов, который использовал MatLab, поэтому я пытаюсь выполнить некоторые из упражнений, которые мы делали в этом классе. Я пытаюсь получить и отобразить FT изображения, чтобы я мог замаскировать некоторые частоты. Я хотел бы видеть FT, поэтому я знаю, насколько велика маска, но когда я попробовал, я получил изображение, подобное этому:
alt text
а не как один из этих
альтернативный текст http://www.ceremade.dauphine.fr/~peyre/numerical-tour/tours/graphics_synthesis_fourier/index_03.png
Я забыл где-нибудь шаг? Я загружаю изображение, преобразовываю его тип в CV_32FC1, получаю его матрицу, получаю ДПФ и затем превращаю полученную матрицу обратно в изображение. Я выложу код, который я использую, если он поможет?
Или если у кого-то есть ссылка на пример отображения FT? Я мог найти только те, которые использовали его для свертки.

РЕДАКТИРОВАТЬ: я получил фазы изображения?

1 Ответ

2 голосов
/ 24 декабря 2010

Я столкнулся с аналогичной проблемой, пытаясь визуализировать величину 2D DFT на изображении относительно OpenCV. Я наконец-то произвел работающую реализацию. Я бы не счел это хорошим кодом, и он был протестирован только на одноканальном изображении размером 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_

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;
    }
...