OpenCV C++二維傅里葉譜和相角陣列

傅里葉變換

    二維DFT的極座標表示

                                        

    幅度或頻率譜爲

                                        

R(u,v)和I(u,v)分別是F(u,v)的實部和虛部

    相角或相位譜爲

                                           

使用書中圖4-24和圖4-25測試,顯示傅里葉譜和相位譜

代碼如下:

#include "opencv2/opencv.hpp"

using namespace cv;

#define PI2 2*3.141592654

int main( int argc, char *argv[] )
{
    const char* filename = argc >=2 ? argv[1] : "lena.jpg";

    Mat image = imread(filename, IMREAD_GRAYSCALE);
    if( image.empty())
        return -1;

    imshow("src",image);
    image.convertTo(image,CV_32FC1);

    ////////////////////////////////////////二維基本傅里葉變換//////////////////////////////////////////////////

//    for(int i=0; i<image.rows; i++) {        //中心化
//        float *p = image.ptr<float>(i);
//        for(int j=0; j<image.cols; j++){
//            p[j] = p[j] * pow(-1, i+j);
//        }
//    }
//    Mat dftRe = Mat::zeros(image.size(), CV_32FC1);
//    Mat dftIm = Mat::zeros(image.size(), CV_32FC1);
//    for(int u=0; u<image.rows; u++)
//    {
//        float *pRe = dftRe.ptr<float>(u);
//        float *pIm = dftIm.ptr<float>(u);
//        for(int v=0; v<image.cols; v++)
//        {
//            float sinDft=0, cosDft=0;
//            for(int i=0; i<image.rows; i++)
//            {
//                float *q = image.ptr<float>(i);
//                for(int j=0; j<image.cols; j++)
//                {
//                    float temp = PI2 *((float)u*i/image.rows + (float)v*j/image.cols);
//                    sinDft -= q[j] * sin(temp);
//                    cosDft += q[j] * cos(temp);
//                }
//            }
//            pRe[v] = sinDft;
//            pIm[v] = cosDft;
//        }
//    }
//    divide(dftRe, image.rows*image.rows, dftRe);
//    divide(dftIm, image.rows*image.rows, dftIm);
//    multiply(dftIm, dftIm, dftIm);
//    multiply(dftRe, dftRe, dftRe);
//    add(dftRe, dftIm, dftRe);
//    pow(dftRe, 0.5, dftRe);
//    imshow("mydft", dftRe);

    ///////////////////////////////////////快速傅里葉變換/////////////////////////////////////////////////////
    int oph = getOptimalDFTSize(image.rows);
    int opw = getOptimalDFTSize(image.cols);
    Mat padded;
    copyMakeBorder(image, padded, 0, oph-image.rows, 0, opw-image.cols, BORDER_CONSTANT, Scalar::all(0));

    Mat temp[] = {padded, Mat::zeros(image.size(),CV_32FC1)};
    Mat complexI;
    merge(temp, 2, complexI);

    dft(complexI, complexI);    //傅里葉變換

    //顯示頻譜圖
    split(complexI, temp);
    Mat amplitude, angle;
    magnitude(temp[0], temp[1], amplitude);
    phase(temp[0], temp[1], angle);
//    cartToPolar(temp[0], temp[1],amplitude, angle);

    int cx = amplitude.cols/2;
    int cy = amplitude.rows/2;
    Mat q0(amplitude, Rect(0, 0, cx, cy));   // Top-Left - Create a ROI per quadrant
    Mat q1(amplitude, Rect(cx, 0, cx, cy));  // Top-Right
    Mat q2(amplitude, Rect(0, cy, cx, cy));  // Bottom-Left
    Mat q3(amplitude, Rect(cx, cy, cx, cy)); // Bottom-Right

    Mat tmp;                           // swap quadrants (Top-Left with Bottom-Right)
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);

    q1.copyTo(tmp);                    // swap quadrant (Top-Right with Bottom-Left)
    q2.copyTo(q1);
    tmp.copyTo(q2);

    Mat amplitude_src;
    divide(amplitude, oph*opw, amplitude_src );

    imshow("amplitude_src",amplitude_src);
    amplitude += Scalar::all(1);                    // switch to logarithmic scale
    log(amplitude, amplitude);
    normalize(amplitude, amplitude, 0, 255, NORM_MINMAX); //歸一化 方便顯示,和實際數據沒有關係
    amplitude.convertTo(amplitude, CV_8U);
    imshow("amplitude",amplitude);

    normalize(angle, angle, 0, 255, NORM_MINMAX); //歸一化 方便顯示,和實際數據沒有關係
    angle.convertTo(angle, CV_8U);
    imshow("angle",angle);

    imwrite("phase.jpg", angle)

    waitKey(0);

    return 1;
}
 

結果:

圖4-24 原圖及原始傅里葉圖

log變換後的傅里葉圖及相位圖

 

圖4-25的圖像

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章