#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace std;
using namespace cv;
int main()
{
    string path = "1.png";
    Mat src = imread(path, 0);
    //【1】创建一个复数矩阵,储存傅里叶变换后的矩阵
    int r = getOptimalDFTSize(src.rows);
    int c = getOptimalDFTSize(src.cols);//得到最优尺寸
    Mat padded;
    //扩充src的边缘,将图像变大( 0, r - src.rows, 0, c - src.cols)分别表示上下左右;
    copyMakeBorder(src, padded, 0, r - src.rows, 0, c - src.cols, BORDER_CONSTANT, ::Scalar::all(0));
    //创建一个复数矩阵,实部为plane[0],虚部plane[1]填充0
    Mat plane[] = { Mat_<float>(padded),Mat::zeros(padded.size(),CV_32F) }; 
    //【2】傅里叶变换
    Mat complexImg;
    merge(plane, 2, complexImg); //可以理解为组合成2通道(实部+虚部)图像
    dft(complexImg, complexImg); //DFT变换后的数据复制到原处,没有另外开辟内存, complexImg是个复数矩阵
    
    int cx = complexImg.cols / 2;
    int cy = complexImg.rows / 2;
    Mat m1(complexImg, cv::Rect(0, 0, cx, cy)); //左上部分
    Mat m2(complexImg, cv::Rect(cx, 0, cx, cy)); //右上部分
    Mat m3(complexImg, cv::Rect(0, cy, cx, cy)); //左下部分
    Mat m4(complexImg, cv::Rect(cx, cy, cx, cy)); //右下部分
    Mat temp;
    m1.copyTo(temp);
    m4.copyTo(m1);
    temp.copyTo(m4);
    m2.copyTo(temp);
    m3.copyTo(m2);
    temp.copyTo(m3);
    Mat partFrequencyImg;
    complexImg.copyTo(partFrequencyImg);
    //变换频率
    int nx1 = int(0.5f*padded.cols);
    int nx2 = int(0.5f*padded.cols);
    int ny1 = int(0.5f*padded.rows);
    int ny2 = int(0.5f*padded.rows);
    //逆变换
    partFrequencyImg.colRange(nx1, nx2+1).setTo(Scalar::all(0));
    partFrequencyImg.rowRange(ny1, ny2+1).setTo(Scalar::all(0));
    Mat iPartDft[] = { Mat::zeros(padded.size(),CV_32F),Mat::zeros(padded.size(),CV_32F) };
    idft(partFrequencyImg, partFrequencyImg);
    split(partFrequencyImg, iPartDft);
    magnitude(iPartDft[0], iPartDft[1], iPartDft[0]);
    cv::normalize(iPartDft[0], iPartDft[0], 1, 0, CV_MINMAX);
    Mat l = iPartDft[0];
    imshow("l", l);
    waitKey(0);
}