傅里叶变换学习参考资料

以下是我学习傅里叶变换过程中参考的一些书籍、网站等,记录下来,方便以后查阅:

DFT:Discrete Fourier Transform 离散傅里叶变换

  1. 傅里叶分析之掐死教程(生动形象,入门必备)

  2. 数字图像处理(第二版)-冈萨雷斯(有大量数学公式,严谨,但有点深奥难懂)

  3. (精心整理)图像的傅里叶变换(有例题解释、图像实例介绍和matlab代码)

  4. 二维DFT具体实现算法

  5. 官方文档:离散傅立叶变换(有opencv实现代码)

  6. OpenCV实现基于傅里叶变换的旋转文本校正(傅里叶变换应用)

我参考(4. DFT实现算法)修改了(5. 官方文档)的代码,主要删除了5中“剪切和重分布幅度图象限”这一步。替换的方法是在进行傅里叶变换之前用(-1)^(x+y)乘以输入的图像函数,就可以将傅里叶变换的原点F(0,0)移到(M/2,N/2)上。效果与官方代码类似。

#include 
#include 
#include 
#include 
#include 


using namespace std;
using namespace cv;


int main()
{   
    //读入图像灰度图
    Mat I = imread("Spectrum.tif", IMREAD_GRAYSCALE);       

    //判断图像是否加载成功
    if (I.empty())
    {
        cout << "图像加载失败!" << endl;
        return -1;
    }
    else
        cout << "图像加载成功!" << endl << endl;

    //(-1)^(x+y)乘以输入的图像函数,将傅里叶变换的原点F(0,0)移到(M/2,N/2)上。
    Mat padded(I.rows,I.cols,CV_32F);
    for (int i = 0;i < I.rows;i++)
    {
        for (int j = 0;j < I.cols;j++)
        {
            float temp= I.at(i, j);
            padded.at<float>(i, j) = temp*pow(-1, i + j);
        }
    }

    //将planes融合合并成一个多通道数组complexI , 初始时实部就是图像
    Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(),CV_32F) };
    Mat complexI;
    merge(planes, 2, complexI);     

    //进行傅里叶变换
    dft(complexI, complexI);

    //计算幅值,planes[0] = Re(DFT(I),planes[1] = Im(DFT(I)) , 即planes[0]为实部,planes[1]为虚部
    split(complexI, planes);        
    magnitude(planes[0], planes[1], planes[0]); 
    Mat magI = planes[0];

    //转换到对数尺度 => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
    magI += Scalar::all(1);
    log(magI, magI);

    //归一化处理,用0-1之间的浮点数将矩阵变换为可视的图像格式
    normalize(magI, magI, 0, 1, CV_MINMAX);

    imshow("输入图像", I);
    imshow("频谱图", magI);    

    waitKey(0);
    return 0;
}

在此基础上,我实现了从离散傅里叶变换到经典低通高通滤波、傅里叶逆变换这一整套流程,代码如下:

#include 
#include 
#include 
#include 
#include 


using namespace std;
using namespace cv;


#define Order 2     //巴特沃斯阶数
#define D0 80       //截止频率
#define PI 3.14159


//理想低通滤波器
void ILPF(Mat src, int d0)
{
    int M = src.rows;
    int N = src.cols;

    for (int i = 0;i < src.rows;i++)
    {
        //src为双通道,所以乘2,j=j+2,pow(j / 2 - N / 2, 2)
        for (int j = 0;j < 2*src.cols;j=j+2)
        {
            int Dx = sqrt(pow(i - M / 2, 2) + pow(j / 2 - N / 2, 2));
            if (Dx > D0)
            {
                src.at<float>(i, j) = 0;
                src.at<float>(i, j+1) = 0;
            }
        }
    }
}


//理想高通滤波器
void IHPF(Mat src, int d0)
{
    int M = src.rows;
    int N = src.cols;

    for (int i = 0;i < src.rows;i++)
    {
        for (int j = 0;j < 2 * src.cols;j = j + 2)
        {
            int Dx = sqrt(pow(i - M / 2, 2) + pow(j / 2 - N / 2, 2));
            if (Dx <= D0)
            {
                src.at<float>(i, j) = 0;
                src.at<float>(i, j + 1) = 0;
            }
        }
    }
}


//巴特沃斯低通滤波器Butterworth
void BLPF(Mat src,int n,int d0)
{
    int M = src.rows;
    int N = src.cols;

    for (int i = 0;i < src.rows;i++)
    {
        for (int j = 0;j < 2 * src.cols;j = j + 2)
        {
            int Dx = sqrt(pow(i - M / 2, 2) + pow(j / 2 - N / 2, 2));
            float Hx = 1 / (1 + pow((Dx / d0), 2 * n));
            //处理实部虚部
            src.at<float>(i, j) = src.at<float>(i, j)*Hx;
            src.at<float>(i, j + 1) = src.at<float>(i, j + 1)*Hx;
        }
    }
}


//巴特沃斯高通滤波器Butterworth
void BHPF(Mat src, int n, int d0)
{
    int M = src.rows;
    int N = src.cols;

    for (int i = 0;i < src.rows;i++)
    {
        for (int j = 0;j < 2 * src.cols;j = j + 2)
        {
            int Dx = sqrt(pow(i - M / 2, 2) + pow(j / 2 - N / 2, 2));
            float Hx;
            //排除Dx为0情况,防止d0/Dx无效
            if (Dx == 0)
                Hx = 0;
            else
                Hx = 1 / (1 + pow((d0 / Dx), 2 * n));
            //处理实部虚部
            src.at<float>(i, j) = src.at<float>(i, j)*Hx;
            src.at<float>(i, j + 1) = src.at<float>(i, j + 1)*Hx;
        }
    }
}


//高斯低通滤波器
void GLPF(Mat src,int sigma)
{
    int M = src.rows;
    int N = src.cols;

    for (int i = 0;i < src.rows;i++)
    {
        for (int j = 0;j < 2 * src.cols;j = j + 2)
        {
            int Dx = sqrt(pow(i - M / 2, 2) + pow(j / 2 - N / 2, 2));
            float Hx = exp(-Dx*Dx / (2 * sigma*sigma));
            //处理实部虚部
            src.at<float>(i, j) = src.at<float>(i, j)*Hx;
            src.at<float>(i, j + 1) = src.at<float>(i, j + 1)*Hx;
        }
    }
}


//高斯高通滤波器
void GHPF(Mat src, int sigma)
{
    int M = src.rows;
    int N = src.cols;

    for (int i = 0;i < src.rows;i++)
    {
        for (int j = 0;j < 2 * src.cols;j = j + 2)
        {
            int Dx = sqrt(pow(i - M / 2, 2) + pow(j / 2 - N / 2, 2));
            float Hx = 1 - exp(-Dx*Dx / (2 * sigma*sigma));
            //处理实部虚部
            src.at<float>(i, j) = src.at<float>(i, j)*Hx;
            src.at<float>(i, j + 1) = src.at<float>(i, j + 1)*Hx;
        }
    }
}


//频域拉普拉斯算子
void Laplacian(Mat src)
{
    int M = src.rows;
    int N = src.cols;

    for (int i = 0;i < src.rows;i++)
    {
        for (int j = 0;j < 2 * src.cols;j = j + 2)
        {
            //float Hx = -4*PI*PI*(i*i+j*j);
            float Hx = -(pow(i - M / 2, 2) + pow(j - N / 2, 2));
            //处理实部虚部
            src.at<float>(i, j) = src.at<float>(i, j)*Hx;
            src.at<float>(i, j + 1) = src.at<float>(i, j + 1)*Hx;
        }
    }
}


int main()
{   
    //读入图像灰度图
    Mat I = imread("Moon2.tif", IMREAD_GRAYSCALE);       

    //判断图像是否加载成功
    if (I.empty())
    {
        cout << "图像加载失败!" << endl;
        return -1;
    }
    else
        cout << "图像加载成功!" << endl << endl;

    //(-1)^(x+y)乘以输入的图像函数,将傅里叶变换的原点F(0,0)移到(M/2,N/2)上。
    Mat padded(I.rows,I.cols,CV_32F);
    for (int i = 0;i < I.rows;i++)
    {
        for (int j = 0;j < I.cols;j++)
        {
            float temp= I.at(i, j);
            padded.at<float>(i, j) = temp*pow(-1, i + j);
        }
    }

    //将planes融合合并成一个多通道数组complexI , 初始时实部就是图像
    Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(),CV_32F) };
    Mat complexI;
    merge(planes, 2, complexI);     

    //进行傅里叶变换及低通高通滤波
    dft(complexI, complexI);
    //ILPF(complexI, D0);
    //BLPF(complexI, Order, D0);
    //GLPF(complexI, D0);
    //IHPF(complexI, D0);
    //BHPF(complexI, Order, D0);
    //GHPF(complexI, D0);
    Laplacian(complexI);
    idft(complexI, complexI);

    //计算对应的幅值=(R^2+I^2)^1/2,planes[0] = Re(DFT(I),planes[1] = Im(DFT(I)) , 即planes[0]为实部,planes[1]为虚部
    split(complexI, planes);
    magnitude(planes[0], planes[1], planes[0]); 
    Mat magI = planes[0];

    //归一化处理,用0-1之间的浮点数将矩阵变换为可视的图像格式
    normalize(magI, magI, 0, 1, CV_MINMAX);

    imshow("输入图像", I);
    imshow("结果图", magI);


    waitKey(0);
    return 0;
}

你可能感兴趣的:(数字图像处理,编程语言)