Emgucv 离散余弦变换 高斯滤波 还原

4 篇文章 0 订阅
2 篇文章 0 订阅

本文用的是emgucv4.1,对图像进行离散傅里叶变换,之后使用高斯滤波,再还原滤波后的图

1、对原图进行离散变换,之后显示频率

 //============================1、将输入图像扩展到最佳的尺寸,边界用0补充
            int m = CvInvoke.GetOptimalDFTSize(glMain8UC1.Rows);
            int n = CvInvoke.GetOptimalDFTSize(glMain8UC1.Cols);
            Mat padded = new Mat();
            CvInvoke.CopyMakeBorder(glMain8UC1, padded, 0, m - glMain8UC1.Rows, 0, n - glMain8UC1.Cols, BorderType.Constant);
            padded.ConvertTo(padded, DepthType.Cv32F); //将padded转换为Cv32F类型,此为傅里叶变换的实部

            //============================2、创建傅里立叶的实部和虚部
            //创建元素值都为0的zeroMat,此为傅里叶变换的虚部
            Mat zeroMat = Mat.Zeros(padded.Rows, padded.Cols, DepthType.Cv32F, 1);
            VectorOfMat matVector = new VectorOfMat(); //创建mat型向量
            matVector.Push(padded); //将padded压入matVector中
            matVector.Push(zeroMat); //将zeroMat压入matVector中
            //创建channel数为2的mat,用于存储傅里叶变换的实部和虚部
            Mat complexI = new Mat(padded.Size, DepthType.Cv32F, 2);
            CvInvoke.Merge(matVector, complexI); //将matVector中存储的2个mat,merge到complexI中

            
            //=============================3、创建mat,用于保存傅里叶变换的结果
            Mat fourier = new Mat(complexI.Size, DepthType.Cv32F, 2);
            //调用傅里叶变换函数Dft,进行傅里叶变换
            CvInvoke.Dft(complexI, fourier, DxtType.Forward, complexI.Rows);

            Mat tempFourier = new Mat(complexI.Size, DepthType.Cv32F, 2);
            fourier.CopyTo(tempFourier);
            
            //=============================4、对结果进行变换显示
            //将复数转换为幅值,即=>log(1+sqrt(Re(DFT(I)^2+Im(DFT(I)^2))
            Mat magnitudeImage = Magnitude(fourier);
            CvInvoke.Log(magnitudeImage, magnitudeImage);
            //若有奇数行或奇数列,则进行频谱裁剪
            magnitudeImage = new Mat(magnitudeImage, new Rectangle(0, 0, magnitudeImage.Cols & -2, magnitudeImage.Rows & -2));
            //重新排列傅里叶图像中的象限,使得原点位于图像中心
            SwitchQuadrants(ref magnitudeImage);
            CvInvoke.Normalize(magnitudeImage, magnitudeImage, 0, 255, NormType.MinMax, DepthType.Cv8U);
            CvInvoke.Imshow("fourier forward", magnitudeImage);

2、对原图进行离散变换后,使用高斯滤波,再还原图像

//============================1、将输入图像扩展到最佳的尺寸,边界用0补充
            int m = CvInvoke.GetOptimalDFTSize(glMain8UC1.Rows);
            int n = CvInvoke.GetOptimalDFTSize(glMain8UC1.Cols);
            Mat padded = new Mat();
            CvInvoke.CopyMakeBorder(glMain8UC1, padded, 0, m - glMain8UC1.Rows, 0, n - glMain8UC1.Cols, BorderType.Constant);
            padded.ConvertTo(padded, DepthType.Cv32F); //将padded转换为Cv32F类型,此为傅里叶变换的实部

            //============================2、创建傅里立叶的实部和虚部

            //创建元素值都为0的zeroMat,此为傅里叶变换的虚部
            Mat zeroMat = Mat.Zeros(padded.Rows, padded.Cols, DepthType.Cv32F, 1);
            VectorOfMat matVector = new VectorOfMat(); //创建mat型向量
            matVector.Push(padded); //将padded压入matVector中
            matVector.Push(zeroMat); //将zeroMat压入matVector中
            //创建channel数为2的mat,用于存储傅里叶变换的实部和虚部
            Mat complexI = new Mat(padded.Size, DepthType.Cv32F, 2);
            CvInvoke.Merge(matVector, complexI); //将matVector中存储的2个mat,merge到complexI中

            //=============================3、创建mat,用于保存傅里叶变换的结果
            Mat fourier = new Mat(complexI.Size, DepthType.Cv32F, 2);
            //调用傅里叶变换函数Dft,进行傅里叶变换
            CvInvoke.Dft(complexI, fourier, DxtType.Forward, complexI.Rows);

            Mat tempFourier = new Mat(complexI.Size, DepthType.Cv32F, 2);
            fourier.CopyTo(tempFourier);

            //==============================4、对应的滤波卷积处理
            this.SwitchQuadrants(ref tempFourier);
            Mat gaoshiKernel = GMLib.GasMat(tempFourier.Size, 55);
            CvInvoke.MulSpectrums(tempFourier, gaoshiKernel, tempFourier, MulSpectrumsType.Default);
            this.SwitchQuadrants(ref tempFourier);

            //==============================5、反傅立叶变换
            Mat fourierInv = new Mat(fourier.Size, DepthType.Cv32F, 2);
            //注意,反变换时,必须用这个参数 DxtType.InvScale
            CvInvoke.Dft(tempFourier, fourierInv, DxtType.InvScale, tempFourier.Rows);

            Mat mainInv32FC1 = Magnitude(fourierInv);
            Mat mainInv8UC1 = new Mat(mainInv32FC1.Size, DepthType.Cv8U, 1);
            CvInvoke.ConvertScaleAbs(mainInv32FC1, mainInv8UC1, 1.0, 1.0);
            CvInvoke.Imshow("mainInv", mainInv8UC1);

3、完整程序在链接中

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值