牛骨文教育服务平台(让学习变的简单)
博文笔记

OpenCV傅立叶正逆变换和频谱处理的例子

创建时间:2016-07-12 投稿人: 浏览次数:2121
  • Opencv中的范例中只给出了傅立叶正变换的生成频谱图像的例子,没有给出逆变换和频谱处理的例子,由于最近工作中要用到,就研究了一下用法,理论是几年前在大学学的,现在忘得差不多了,只是简单的回顾了下,所以理论方面就不多论述了,直接看代码。
C/C++
    //这是范例中生成频谱图的代码,对其中部分进行了改动,
    int M = getOptimalDFTSize( img.rows );
    int N = getOptimalDFTSize( img.cols );
    Mat padded;
    copyMakeBorder(img, padded, 0, M - img.rows, 0, N - img.cols, BORDER_CONSTANT, Scalar::all(0));
    Mat planes[2] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)};
    Mat ImgDFT;
    merge(planes, 2, ImgDFT);

    dft(ImgDFT, ImgDFT);
    //正变换过后,先对频谱图进行中心平移
    ImgDFT = ImgDFT(Rect(0, 0, ImgDFT.cols & -2, ImgDFT.rows & -2));

    int cx = ImgDFT.cols/2;
    int cy = ImgDFT.rows/2;
    // rearrange the quadrants of Fourier image
    // so that the origin is at the image center
    Mat tmp;
    Mat q0(ImgDFT, Rect(0, 0, cx, cy));
    Mat q1(ImgDFT, Rect(cx, 0, cx, cy));
    Mat q2(ImgDFT, Rect(0, cy, cx, cy));
    Mat q3(ImgDFT, Rect(cx, cy, cx, cy));
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);

    q1.copyTo(tmp);
    q2.copyTo(q1);
    tmp.copyTo(q2);  
    //将得到的频谱图分解成虚部和实部两部分
    split(ImgDFT,planes);
    Mat Proc_RE = planes[0];
    Mat Proc_IM = planes[1];

/*******************************************************/
//此处定义处理频谱的方法,实部和虚部要分开分别进行处理
    double ESP = 0.000001;
    for( int i = 0; i < Proc_RE.rows; ++i )
        for( int j = 0; j < Proc_RE.cols; ++j )
        {
            double dx = i - Proc_RE.rows/2;
            double dy = j - Proc_RE.cols/2;
            Proc_RE.at<float>(i, j) = (1 - exp(-100/(pow(dx, 2) + pow(dy, 2) + ESP)))* Proc_RE.at<float>(i, j);
            Proc_IM.at<float>(i, j) = (1 - exp(-100/(pow(dx, 2) + pow(dy, 2) + ESP)))* Proc_IM.at<float>(i, j);
        }
/*******************************************************/
#if 1
    //此处用于显示处理后的频谱图像(频谱为傅立叶变换的幅值,magnitude()函数可以直接求得),
    Mat mag;
    magnitude(planes[0], planes[1], mag);
    mag += Scalar::all(1);
    log(mag, mag);
    normalize(mag, mag, 0, 1, CV_MINMAX);
    imshow("spectrum magnitude", mag);
    waitKey();    
#endif // 1
    //将处理后的虚部和实部矩阵合成一个矩阵,并进行中心平移,还原回(0,2π)的图像
    merge(planes, 2, ImgDFT);
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);

    q1.copyTo(tmp);
    q2.copyTo(q1);
    tmp.copyTo(q2);
    //进行逆变换,归一化,并将尺寸调整为处理前的图像尺寸
    idft(ImgDFT, ImgDFT,  DFT_SCALE | DFT_REAL_OUTPUT);//1
    //idft(ImgDFT, ImgDFT);//2
    //split(ImgDFT, planes);
    //为了后续的处理,此处的imp矩阵有两种选择方法:1、直接用Opencv提供的参数,生成输出图像(ImgDFT);
    //2、使用2函数逆变换,然后将矩阵分解,选择实数部分为输出图像矩阵(planes[0])注:数字图像处理第三
    // 版(冈萨雷斯)上说:为了消除计算不准确导致的寄生复分量,所以只取实部。
    Mat imp = ImgDFT;
    normalize(imp, imp, 0, 255, CV_MINMAX);
    imp.convertTo(imp, CV_8U);
    Mat Output = imp(Range(0, img.rows), Range(0, img.cols));
    imshow("Output",Output);
    waitKey(0);

实验处理用原图
生成的频谱图像
本实验处理算法(低通滤波器)处理后的频谱图像
处理后的图像

  • 参考文献:
    [1] 冈萨雷斯.数字图象处理(第三版)[M].北京:电子工业出版社,2011.6.
    [2] www.opencv.org.cn .

  • 如有错误,欢迎指正!

  • 尊重原创,转载请注明出处

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。