opencv学习笔记26-opencv相位谱和还原归一化时的系数

一、函数: 

opencv学习笔记24-opencv图像的傅里叶变换(幅值谱)

二、示例代码:

#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>           
#include <opencv2/videoio.hpp>       
#include <opencv2/objdetect.hpp>        
#include <opencv2/highgui/highgui_c.h>  
#include <iostream>                     

using namespace cv;                    
using namespace std;      


int calcVisbalDft(cv::Mat srcMat, cv::Mat& magMat, cv::Mat& ph, double& normVal);

int main()
{
	utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);
	Mat srcMat = imread("C:\\Users\\86173\\Desktop\\TI\\Q版阿离.png", 0);

	Mat ph_image;
	Mat ma_image;
	double normVal;

	if (srcMat.empty()) {
		cout << "failed to read image!:" << endl;
		return -1;
	}
	
	calcVisbalDft(srcMat, ma_image, ph_image, normVal);
	cout << "normVal:" << endl;
	cout << normVal << endl;

	imshow("原始图像", srcMat);//原始图像
	imshow("幅度谱", ma_image);//幅度谱
	imshow("相位谱", ph_image);//相位谱

	waitKey(0);
	return 0;
}




//输入图片,输出幅值谱,相位谱和还原归一化时的系数(最大值)
int calcVisbalDft(Mat srcMat, Mat& magMat, Mat& ph, double& normVal)
{
	 Mat dst;
	 srcMat = imread("C:\\Users\\86173\\Desktop\\TI\\Q版阿离.png", 0);

	int m = getOptimalDFTSize(srcMat.rows); //2,3,5的倍数有更高效率的傅里叶变换
	int n = getOptimalDFTSize(srcMat.cols);
	Mat output_image;
	//把灰度图像放在左上角,在右边和下边扩展图像,扩展部分填充为0;
	copyMakeBorder(srcMat, output_image, 0, m - srcMat.rows, 0, n - srcMat.cols, BORDER_CONSTANT, Scalar::all(0));

	//planes[0]为dft变换的实部,planes[1]为虚部,ph为相位, plane_true=mag为幅值
	Mat planes[] = { Mat_<float>(output_image), Mat::zeros(output_image.size(), CV_32F) };
	Mat planes_true = Mat_<float>(output_image);

	//保存相位(Mat_代表确定了数据类型,访问元素时不需要再指定元素类型)
	ph = Mat_<float>(output_image);

	Mat complexImg;
	//多通道complexImg既有实部又有虚部

	merge(planes, 2, complexImg);
	//对上边合成的mat进行傅里叶变换,***支持原地操作***,傅里叶变换结果为复数.通道1存的是实部,通道二存的是虚部
	dft(complexImg, complexImg);
	//把变换后的结果分割到两个mat,一个实部,一个虚部,方便后续操作
	split(complexImg, planes);

	//此部分目的为更好地显示幅值
	magnitude(planes[0], planes[1], planes_true);//幅度谱mag
	phase(planes[0], planes[1], ph);//相位谱ph
	Mat A = planes[0];
	Mat B = planes[1];
	 magMat = planes_true;

	magMat += Scalar::all(1);//对幅值加1
	//计算出的幅值一般很大,达到10^4,通常没有办法在图像中显示出来,需要对其进行log求解。
	log(magMat, magMat);

	//取矩阵中的最大值,便于后续还原时去归一化
	minMaxLoc(magMat, 0, &normVal, 0, 0);

	//修剪频谱,如果图像的行或者列是奇数的话,那其频谱是不对称的,因此要修剪
	magMat = magMat(Rect(0, 0, magMat.cols & -2, magMat.rows & -2));
	ph = ph(Rect(0, 0, magMat.cols & -2, magMat.rows & -2));
	Mat _magI = magMat.clone();
	//将幅度归一化到可显示范围。
	normalize(_magI, _magI, 0, 1, CV_MINMAX);

	//显示规则频谱图
	int cx = magMat.cols / 2;
	int cy = magMat.rows / 2;

	//这里是以中心为标准,把mag图像分成四部分
	Mat tmp;
	Mat quadrant0(magMat, Rect(0, 0, cx, cy));
	Mat quadrant1(magMat, Rect(cx, 0, cx, cy));
	Mat quadrant2(magMat, Rect(0, cy, cx, cy));
	Mat quadrant3(magMat, Rect(cx, cy, cx, cy));
	quadrant0.copyTo(tmp);
	quadrant3.copyTo(quadrant0);
	tmp.copyTo(quadrant3);
	quadrant1.copyTo(tmp);
	quadrant2.copyTo(quadrant1);
	tmp.copyTo(quadrant2);

	normalize(magMat, magMat, 1, 0, CV_MINMAX);
	
	return 0;
}

三、运行结果:

11022b9071a3458c9ae257645e4adf79.png

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值