编程语言
首页 > 编程语言> > 图像的傅里叶变换和逆变换C++版

图像的傅里叶变换和逆变换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