图像的傅里叶变换和逆变换C++版
作者:互联网
首先把整体程序分段,每段都是单独的功能。最后再把完整代码给出:
头文件:包含OpenCV和标准库输出调试
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char*argv[]){
waitKey(0);
return 0;
}
读入并显示原图
Mat img = imread("2.png");
if (!img.data)
return -1;
namedWindow("原图", WINDOW_AUTOSIZE);
imshow("原图", img);
进行离散傅里叶变换和逆变换
//快速傅里叶变换
void ImageDFT(InputArray srcImage, OutputArray dstImage)
{
//得到Mat类型
Mat src = srcImage.getMat();
int rows = src.rows;
int cols = src.cols;
//快速傅里叶变换的计算速度与图像的大小有关,计算最优图像尺寸,然后进行扩充,扩充值为0
Mat padded;
int rPadded = getOptimalDFTSize(rows);
int cPadded = getOptimalDFTSize(cols);
copyMakeBorder(src, padded, 0, rPadded - rows, 0, cPadded - cols, BORDER_CONSTANT, Scalar::all(0));
//快速的傅里叶变换(双通道:用于存储实部 和 虚部)
dft(padded, dstImage, DFT_COMPLEX_OUTPUT);
}
//转换成灰度图,浮点型图
Mat fImg;
cvtColor(img, img, CV_BGR2GRAY);
img.convertTo(fImg, CV_64FC1);
//快速傅里叶变换
Mat fftImage;
ImageDFT(fImg, fftImage);
//傅里叶逆变换
Mat image;
cv::dft(fftImage, image, DFT_INVERSE + DFT_REAL_OUTPUT + DFT_SCALE);
namedWindow("fft逆变换图", WINDOW_AUTOSIZE);
imshow("fft逆变换图", image);
显示傅里叶变换图
Mat planes[2];
split(fftImage, planes);
cout << fftImage.channels() << endl;
magnitude(planes[0], planes[1], planes[0]);
Mat magnitudeImage = planes[0];
magnitudeImage += Scalar::all(1); // 所有的像素都加1
log(magnitudeImage, magnitudeImage); // 求自然对数
normalize(magnitudeImage, magnitudeImage, 0, 1, NORM_MINMAX);
// 频谱图像长宽变为偶数,然后频谱中心化
magnitudeImage = magnitudeImage(Rect(0, 0, magnitudeImage.cols & -2, magnitudeImage.rows & -2));
int cx = magnitudeImage.cols / 2;
int cy = magnitudeImage.rows / 2;
Mat q0(magnitudeImage, Rect(0, 0, cx, cy));
Mat q1(magnitudeImage, Rect(cx, 0, cx, cy));
Mat q2(magnitudeImage, Rect(0, cy, cx, cy));
Mat q3(magnitudeImage, Rect(cx, cy, cx, cy));
Mat tmp;
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
imshow("fft图", magnitudeImage);
完整代码:
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
#include <iostream>
using std::cout;
using std::endl;
//快速傅里叶变换
void ImageDFT(InputArray srcImage, OutputArray dstImage)
{
//得到Mat类型
Mat src = srcImage.getMat();
//判断位深
//CV_Assert(src.type() == CV_32FC1 || src.type() == CV_64FC1);
//CV_Assert(src.channels() == 1 || src.channels() == 2);
int rows = src.rows;
int cols = src.cols;
//快速傅里叶变换的计算速度与图像的大小有关,计算最优图像尺寸,然后进行扩充,扩充值为0
Mat padded;
int rPadded = getOptimalDFTSize(rows);
int cPadded = getOptimalDFTSize(cols);
copyMakeBorder(src, padded, 0, rPadded - rows, 0, cPadded - cols, BORDER_CONSTANT, Scalar::all(0));
//快速的傅里叶变换(双通道:用于存储实部 和 虚部)
dft(padded, dstImage, DFT_COMPLEX_OUTPUT);
}
int main(int argc, char*argv[])
{
//输入图像矩阵
//Mat img = imread("2.png", CV_LOAD_IMAGE_GRAYSCALE);
Mat img = imread("2.png");
if (!img.data)
return -1;
namedWindow("原图", WINDOW_AUTOSIZE);
imshow("原图", img);
//转换成灰度图,浮点型图
Mat fImg;
cvtColor(img, img, CV_BGR2GRAY);
img.convertTo(fImg, CV_64FC1);
//快速傅里叶变换
Mat fftImage;
ImageDFT(fImg, fftImage);
//傅里叶逆变换
Mat image;
cv::dft(fftImage, image, DFT_INVERSE + DFT_REAL_OUTPUT + DFT_SCALE);
Mat planes[2];
split(fftImage, planes);
cout << fftImage.channels() << endl;
magnitude(planes[0], planes[1], planes[0]);
Mat magnitudeImage = planes[0];
magnitudeImage += Scalar::all(1); // 所有的像素都加1
log(magnitudeImage, magnitudeImage); // 求自然对数
normalize(magnitudeImage, magnitudeImage, 0, 1, NORM_MINMAX);
magnitudeImage = magnitudeImage(Rect(0, 0, magnitudeImage.cols & -2, magnitudeImage.rows & -2));
int cx = magnitudeImage.cols / 2;
int cy = magnitudeImage.rows / 2;
Mat q0(magnitudeImage, Rect(0, 0, cx, cy));
Mat q1(magnitudeImage, Rect(cx, 0, cx, cy));
Mat q2(magnitudeImage, Rect(0, cy, cx, cy));
Mat q3(magnitudeImage, Rect(cx, cy, cx, cy));
//交换象限(左上与右下进行交换)
Mat tmp;
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
//交换象限(右上与左下进行交换)
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
imshow("fft图", magnitudeImage);
//裁剪傅里叶逆变换
image = image(Rect(0, 0, img.cols, img.rows));
image.convertTo(image, CV_8UC1);
namedWindow("逆变换图", WINDOW_AUTOSIZE);
imshow("逆变换图", image);
waitKey(0);
return 0;
}
参考文献:
https://www.zhihu.com/question/355013340
https://blog.csdn.net/xddwz/article/details/110938652
https://blog.csdn.net/Moment3/article/details/79333781?utm_source=blogxgwz7
https://blog.csdn.net/qazwsxrx/article/details/104672192
标签:src,Mat,img,int,C++,傅里叶,CV,逆变换 来源: https://blog.csdn.net/tiao_god/article/details/112173075