EMGU.CV入门(十七、傅里叶变换)

22 篇文章 29 订阅
21 篇文章 0 订阅

一、效果

在这里插入图片描述

二、代码

 //  1.加载原图
var image1 = new Image<Bgr, byte>("bird1.png");
var image0 = image1.Mat.Clone();
PreviewImage1 = new WriteableBitmap(Bitmap2BitmapImage(Text(image1.Bitmap, "原图")));

// 2. 原图转灰度
var imgGray = new Mat();
CvInvoke.CvtColor(image0, imgGray, ColorConversion.Bgr2Gray);
PreviewImage2 = new WriteableBitmap(Bitmap2BitmapImage(Text(imgGray.Bitmap, "灰度")));

// 3. 傅里叶变换前需要转换为float型,且有实部和虚部
var imgR= imgGray.Clone();
imgR.ConvertTo(imgR,DepthType.Cv32F);
var imgI = Mat.Zeros(imgGray.Rows,imgGray.Cols,DepthType.Cv32F,1);
VectorOfMat vectorOfMat = new VectorOfMat();
vectorOfMat.Push(imgR);
vectorOfMat.Push(imgI);
var img = new Mat(imgR.Size,DepthType.Cv32F,2);
CvInvoke.Merge(vectorOfMat,img);

// 4. 傅里叶变换
Mat fourier = new Mat(imgR.Size, DepthType.Cv32F, 2);
CvInvoke.Dft(img, fourier,DxtType.Forward,imgR.Rows);

// 5. 将复数转换为振幅 log(1+sqrt(Re(DFT(I)^2+Im(DFT(I)^2))
Mat magnitudeImage = Magnitude(fourier);

// 6. 将频率低的显示在中心
SwitchQuadrants(ref magnitudeImage);

// 7. 归一化之后才能显示
var img7 = magnitudeImage.Clone(); 
CvInvoke.Normalize(magnitudeImage, magnitudeImage, 0, 255, NormType.MinMax, DepthType.Cv8U);
PreviewImage3 = new WriteableBitmap(Bitmap2BitmapImage(Text(magnitudeImage.Bitmap, "傅里叶变换")));
//将复数转换为幅值,并进行对数尺度缩放
private Mat Magnitude(Mat fftData)
{
	//傅里叶变换的实部
	Mat Real = new Mat(fftData.Size, DepthType.Cv32F, 1);
	//傅里叶变换的虚部
	Mat Imaginary = new Mat(fftData.Size, DepthType.Cv32F, 1);
	VectorOfMat channels = new VectorOfMat();
	CvInvoke.Split(fftData, channels); //将多通道mat分离成几个单通道mat
	Real = channels.GetOutputArray().GetMat(0);
	Imaginary = channels.GetOutputArray().GetMat(1);
	CvInvoke.Pow(Real, 2.0, Real);
	CvInvoke.Pow(Imaginary, 2.0, Imaginary);
	CvInvoke.Add(Real, Imaginary, Real);
	CvInvoke.Pow(Real, 0.5, Real);
	Mat onesMat = Mat.Ones(Real.Rows, Real.Cols, DepthType.Cv32F, 1);
	CvInvoke.Add(Real, onesMat, Real);
	CvInvoke.Log(Real, Real); //求自然对数
	return Real;
}

//重新排列傅里叶图像中的象限,使得原点位于图像中心
private void SwitchQuadrants(ref Mat mat)
{
	int cx = mat.Cols / 2;
	int cy = mat.Rows / 2;
	Mat q0 = new Mat(mat, new Rectangle(0, 0, cx, cy)); //ROI左上区域
	Mat q1 = new Mat(mat, new Rectangle(cx, 0, cx, cy)); //ROI右上区域
	Mat q2 = new Mat(mat, new Rectangle(0, cy, cx, cy)); //ROI左下区域
	Mat q3 = new Mat(mat, new Rectangle(cx, cy, cx, cy)); //ROI右下区域
	Mat temp = new Mat(q0.Size, DepthType.Cv32F, 1);
	//交换象限(左上和右下进行交换)
	q0.CopyTo(temp);
	q3.CopyTo(q0);
	temp.CopyTo(q3);
	//交换象限(右上和左下进行交换)
	q1.CopyTo(temp);
	q2.CopyTo(q1);
	temp.CopyTo(q2);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值