OpenCvSharp傅里叶变换

using System;
using OpenCvSharp;
using System.Collections.Generic;

namespace FourierTransform
{
    class Program
    {


        private Mat Magnitude(Mat fftData)
        {
            //傅里叶变换的实部
            Mat Real = new Mat(fftData.Size(), MatType.CV_32FC1);
            //傅里叶变换的虚部
            Mat Imaginary = new Mat(fftData.Size(), MatType.CV_32FC1);
            Mat[] channels;
            Cv2.Split(fftData, out channels); //将多通道mat分离成几个单通道mat
            Real = channels[0];
            Imaginary = channels[1];
            Cv2.Pow(Real, 2.0, Real);
            Cv2.Pow(Imaginary, 2.0, Imaginary);
            Cv2.Add(Real, Imaginary, Real);
            Cv2.Pow(Real, 0.5, Real);
            Mat onesMat = Mat.Ones(Real.Rows, Real.Cols, MatType.CV_32FC1);
            Cv2.Add(Real, onesMat, Real);
            Cv2.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 Rect(0, 0, cx, cy)); //ROI左上区域
            Mat q1 = new Mat(mat, new Rect(cx, 0, cx, cy)); //ROI右上区域
            Mat q2 = new Mat(mat, new Rect(0, cy, cx, cy)); //ROI左下区域
            Mat q3 = new Mat(mat, new Rect(cx, cy, cx, cy)); //ROI右下区域
            Mat temp = new Mat(q0.Size(), MatType.CV_32FC1);
            //交换象限(左上和右下进行交换)
            q0.CopyTo(temp);
            q3.CopyTo(q0);
            temp.CopyTo(q3);
            //交换象限(右上和左下进行交换)
            q1.CopyTo(temp);
            q2.CopyTo(q1);
            temp.CopyTo(q2);
        }


        static void Main(string[] args)
        {

            // 使用eye()函数定义指定大小(rows X cols)和类型(type)的单位矩阵



            Mat image = Cv2.ImRead(@" ", ImreadModes.Grayscale);    // Cv2.ImShow("padded", image);

            //2、输入图像延扩到最佳的尺寸,边界用0补充
            int m = Cv2.GetOptimalDFTSize(image.Rows);
            int n = Cv2.GetOptimalDFTSize(image.Cols);


            Mat padded = new Mat();

            // 在图像周围形成边框(下边框以及右边框)
            Cv2.CopyMakeBorder(image, padded, 0, m - image.Rows, 0, n - image.Cols, BorderTypes.Constant, Scalar.All(0));

            //3、为傅里叶变换的结果分配存储空间

            //傅里叶变换要float类型,将padded转换为Cv32F类型,此为傅里叶变换的实部

            //频域范围远远大于其空间对应物。因此,我们通常至少以浮动格式存储它们。因此,我们将把我们的输入图像转换为这种类型,并用另一个通道来展开,以保持复杂的值:
            padded.ConvertTo(padded, MatType.CV_32F);

            //创建元素值都为0的zeroMat,此为傅里叶变换的虚部(添加到扩展的另一个带零的平面)
            Mat zeroMat = Mat.Zeros(padded.Rows, padded.Cols, MatType.CV_32FC1);//CV_32F
            //将planes数组组合合并成一个多通道的数组complexI
            Mat[] planes = { padded, zeroMat };
            //创建channel数为2的mat,用于存储傅里叶变换的实部和虚部
            Mat complexI = new Mat(padded.Size(), MatType.CV_32FC2);



            //合成:注意图像显示只能为单通道、三通道、四通道。其它数量的通道合成,系统会报错。通道合成也可以为三通道图像加单通道合成为四通道
            Cv2.Merge(planes, complexI);

            Mat fourier = new Mat(complexI.Size(), MatType.CV_32FC2);

            //调用傅里叶变换函数Dft,进行傅里叶变换
            //第三个参数为变换标识符,默认取零为正向变换,取其他值时:
            Cv2.Dft(complexI, fourier, DftFlags.None, complexI.Rows);

            var mc = new Program();
            //将复数转换为幅值
            Mat magnitudeImage = mc.Magnitude(fourier);

            //若有奇数行或奇数列,则进行频谱裁剪
            magnitudeImage = new Mat(magnitudeImage, new Rect(0, 0, magnitudeImage.Cols & -2, magnitudeImage.Rows & -2));// a & -2 代表最大不超过a的偶数
            //Cv2.Normalize(magnitudeImage, magnitudeImage, 0, 255, NormTypes.MinMax, MatType.CV_8U);

            //Cv2.ImShow("JJ", magnitudeImage);
            //重新排列傅里叶图像中的象限,使得原点位于图像中心
            mc.SwitchQuadrants(ref magnitudeImage);

            //归一化,用0到1之间的浮点值将矩阵变换为可视的图像格式
            //类型一定要是Cv8U,否则图片在imageBox控件中显示为纯黑色图片
            Cv2.Normalize(magnitudeImage, magnitudeImage, 0, 255, NormTypes.MinMax, MatType.CV_8U);


            //magnitudeImage.ConvertTo(magnitudeImage, MatType.CV_8U);
            Cv2.ImShow("频谱幅值", magnitudeImage);
            //Cv2.Normalize(magnitudeImage, magnitudeImage, 1, 0, NormTypes.MinMax, MatType.CV_32F);

            //Cv2.ImShow("频谱幅值", magnitudeImage);


            Cv2.WaitKey(0);
            // Console.Write(a);

            Console.Read();

        }
    }
}

你可能感兴趣的:(计算机视觉,opencv,人工智能,c#,图像处理)