opencv显示图像的傅里叶谱图像(频谱)源代码详解

1. 频率域

通过傅里叶变换连接空间域和频率域,其是频率域滤波的基础。这里将结合opencv中的sample文档(\source\sample目录下的dft.cpp),对一副灰度图像进行傅里叶变换,并显示其傅里叶谱图像。

 

2. 傅里叶谱显示

 

#include<opencv.hpp>
#include<iostream>

int main(void)
{
	//加载一副灰度图像
	cv::Mat src=cv::imread("D:/Opencv Picture/Lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);
	if (!src.data)
	{
		std::cout << "Image Load Fail!!!" << "\n";
		return 1;
	}
	cv::imshow("SRC", src);

	//扩充图像尺寸到最佳尺寸,边界用0填充
	int r = cv::getOptimalDFTSize(src.rows);
	int c = cv::getOptimalDFTSize(src.cols);
	cv::Mat padded;
	cv::copyMakeBorder(src, padded, 0, r - src.rows, 0, c - src.cols,         
    cv::BORDER_CONSTANT,cv::Scalar::all(0));

	//为傅里叶变换的结果(复数,包含实部和虚部,所以需要创建一个二维的数组)分配存储空间,
	//需要用至少float型来存储
	//最后将二维数组合并为二通道--傅里叶变换需要
	cv::Mat dst1[] = { cv::Mat_<float>(padded), cv::Mat::zeros(padded.size(), CV_32F) };
	cv::Mat dst2;
	cv::merge(dst1,2, dst2);

	//傅里叶变换,结果依旧存储在dst2中
	cv::dft(dst2, dst2);

	//将复数换算成幅值
	cv::split(dst2, dst1);//把二通道图像分解为二维数组,保存到dst1中,dst1[0]中存放的为实部
	cv::magnitude(dst1[0], dst1[1], dst1[0]);//结果存放在dst1[0]中
	cv::Mat magnitudeImage = dst1[0];


	//对数尺度缩放以便于显示
	//计算log(1 + sqrt(Re(DFT(dst2))**2 + Im(DFT(dst2))**2))
	magnitudeImage += cv::Scalar::all(1);
	cv::log(magnitudeImage, magnitudeImage);


	//剪切和重分布幅度图象限
	//若有奇数行或奇数列,进行频谱裁剪
	magnitudeImage = magnitudeImage(cv::Rect(0, 0, magnitudeImage.cols & -2, magnitudeImage.rows & -2));//任何一个数&-2的结果一定是偶数

	//重新排列傅里叶图像的象限,使原点位于图像中心
	int cx = magnitudeImage.cols / 2;
	int cy = magnitudeImage.rows / 2;
	cv::Mat q0(magnitudeImage(cv::Rect(0, 0, cx, cy)));
	cv::Mat q1(magnitudeImage(cv::Rect(cx, 0, cx, cy)));
	cv::Mat q2(magnitudeImage(cv::Rect(0, cy, cx, cy)));
	cv::Mat q3(magnitudeImage(cv::Rect(cx, cy, cx, cy)));

	cv::Mat tmp;
	q0.copyTo(tmp);
	q3.copyTo(q0);
	tmp.copyTo(q3);
	q1.copyTo(tmp);
	q2.copyTo(q1);
	tmp.copyTo(q2);


	//将幅度值归一化到0~1之间,这是因为magnitudeImage中的数据类型是浮点型,这时用imshow()来显示函数,会将像素值乘于255,因此需要归一化到0~1之间
	cv:normalize(magnitudeImage, magnitudeImage, 0, 1, cv::NORM_MINMAX);

	//显示最后的频谱
	cv::imshow("spectrum magnitude", magnitudeImage);

	cv::waitKey();

	return 0;
}


3. 显示结果

 

运行结果如下。

下面来一步步看看,各个步骤的作用。如果不进行归一化处理的结果如下图所示,整个画面发白,根本看不到任何信息。

 

如果不进行象限调整,结果如下,低频出现在图片的四个角(四角发亮),而通过调整之后将低频调整到了原点附近。

 

如果不进行尺度调整,可以发现对比度不高,仅仅能看到中心一个亮点,说明尺度调整后,能显示更多细节。



 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值