且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

Win8 Metro(C#)数字图像处理--2.53图像傅立叶变换

更新时间:2022-09-27 14:27:22

原文:Win8 Metro(C#)数字图像处理--2.53图像傅立叶变换



[函数名称]

1,一维FFT变换函数         Complex[] FFT(Complex[] sourceData, int countN)

  2,二维FFT变换函数           Complex[] FFT2(byte[] imageData,bool inv)

  3,图像傅立叶变换幅度函数     WriteableBitmap FFTImage()

  4,图像傅立叶变换相位函数     WriteableBitmap FFTPhaseImage()

[算法说明]

  关于傅立叶变换这一小节,由于算法较为复杂,因此在后面专门介绍,这里略去。

[函数代码]

  代码包括两个类库:1,复数运算类Complex.cs   2,FFT变换类DFT.cs

1.Complex.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Win8ImageProcess
{
    class Complex
    {
        //复数实部
        private double real = 0.0;
        //复数虚部
        private double imaginary = 0.0;

        public double Real
        {
            get
            {
                return real;
            }
            set
            {
                real = value;
            }
        }

        public double Imaginary
        {
            get
            {
                return imaginary;
            }
            set
            {
                imaginary = value;
            }
        }

        public Complex()
        {
        }

        public Complex(double dbreal, double dbimag)
        {
            real = dbreal;
            imaginary = dbimag;
        }

        public Complex(Complex other)
        {
            real = other.real;
            imaginary = other.imaginary;
        }
        //复数加运算
        public static Complex operator +(Complex comp1, Complex comp2)
        {
            return comp1.Add(comp2);
        }
        //复数减运算
        public static Complex operator -(Complex comp1, Complex comp2)
        {
            return comp1.Subtract(comp2);
        }
        //复数乘运算
        public static Complex operator *(Complex comp1, Complex comp2)
        {
            return comp1.Multiply(comp2);
        }

        public Complex Add(Complex comp)
        {
            double x = real + comp.real;
            double y = imaginary + comp.imaginary;

            return new Complex(x, y);
        }

        public Complex Subtract(Complex comp)
        {
            double x = real - comp.real;
            double y = imaginary - comp.imaginary;

            return new Complex(x, y);
        }

        public Complex Multiply(Complex comp)
        {
            double x = real * comp.real - imaginary * comp.imaginary;
            double y = real * comp.imaginary + imaginary * comp.real;

            return new Complex(x, y);
        }
        //幅值
        public double Abs()
        {
            double x = Math.Abs(real);
            double y = Math.Abs(imaginary);

            if (real == 0)
            {
                return y;
            }
            if (imaginary == 0)
            {
                return x;
            }

            if (x > y)
            {
                return (x * Math.Sqrt(1 + (y / x) * (y / x)));
            }
            else
            {
                return (y * Math.Sqrt(1 + (x / y) * (x / y)));
            }
        }
        //相位角
        public double Angle()
        {
            if (real == 0 && imaginary == 0)
                return 0;

            if (real == 0)
            {
                if (imaginary > 0)
                    return Math.PI / 2;
                else
                    return -Math.PI / 2;
            }
            else
            {
                if (real > 0)
                    return Math.Atan2(imaginary, real);
                else
                {
                    if (imaginary >= 0)
                        return Math.Atan2(imaginary, real) + Math.PI;
                    else
                        return Math.Atan2(imaginary, real) - Math.PI;
                }
            }
        }
        //共轭
        public Complex Conjugate()
        {
            return new Complex(this.real, -this.imaginary);
        }
    }
}
2.DFT.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Windows.UI.Xaml.Media.Imaging;
using System.Runtime.InteropServices.WindowsRuntime;


namespace Win8ImageProcess
{
    public sealed class DFTClass
    {
        private static WriteableBitmap srcImage;
        private static byte[] imageData;
        private static int w = 0;
        private static int h = 0;

        public DFTClass(WriteableBitmap image)
        {
            srcImage = image;
            w = image.PixelWidth;
            h = image.PixelHeight;
        }
        //一维FFT变换 
        private Complex[] FFT(Complex[] sourceData, int countN)
        {
            //求fft的级数
            int r = Convert.ToInt32(Math.Log(countN, 2));
            //定义加权系数W
            Complex[] w = new Complex[countN / 2];
            Complex[] interVar1 = new Complex[countN];
            Complex[] interVar2 = new Complex[countN];
            interVar1 = (Complex[])sourceData.Clone();
            //求取加权系数W
            double angle = 0;
            for (int i = 0; i < countN / 2; i++)
            {
                angle = -i * Math.PI * 2 / countN;
                w[i] = new Complex(Math.Cos(angle), Math.Sin(angle));
                angle = 0;
            }
            int interval = 0;
            int halfN = 0;
            int gap = 0;
            //核心部分
            for (int i = 0; i < r; i++)
            {
                interval = 1 << i;
                halfN = 1 << (r - i);
                for (int j = 0; j < interval; j++)
                {
                    gap = j * halfN;
                    for (int k = 0; k < halfN / 2; k++)
                    {
                        interVar2[k + gap] = interVar1[k + gap] + interVar1[k + gap + halfN / 2];
                        interVar2[k + halfN / 2 + gap] = (interVar1[k + gap] - interVar1[k + gap + halfN / 2]) * w[k * interval];
                    }
                }
                interVar1 = (Complex[])interVar2.Clone();
            }
            uint rev = 0;
            uint num = 0;
            for (uint j = 0; j < countN; j++)
            {
                rev = 0;
                num = j;
                for (int i = 0; i < r; i++)
                {
                    rev <<= 1;
                    rev |= num & 1;
                    num >>= 1;
                }
                interVar2[rev] = interVar1[j];
            }
            return interVar2;
        }
        //二维fft变换
        private Complex[] FFT2(byte[] imageData,bool inv)
        {
            int bytes = w * h;
            byte[] bmpValues = new byte[bytes];
            Complex[] tempCom1 = new Complex[bytes];
            bmpValues = (byte[])imageData.Clone();
            for (int i = 0; i < bytes; i++)
            {
                if (inv == true)
                {
                    if ((i / w + i % w) % 2 == 0)
                    {
                        tempCom1[i] = new Complex(bmpValues[i], 0);
                    }
                    else
                    {
                        tempCom1[i] = new Complex(-bmpValues[i], 0);
                    }
                }
                else
                {
                    tempCom1[i] = new Complex(bmpValues[i], 0);
                }
            }
            Complex[] tempCom2 = new Complex[w];
            Complex[] tempCom3 = new Complex[w];
            for (int i = 0; i < h; i++)//水平方向
            {
                for (int j = 0; j < w; j++)
                {
                    tempCom2[j] = tempCom1[i * w + j];
                }
                tempCom3 = FFT(tempCom2, w);
                for (int j = 0; j < w; j++)
                {
                    tempCom1[i * w + j] = tempCom3[j];
                }
            }
            Complex[] tempCom4 = new Complex[h];
            Complex[] tempCom5 = new Complex[h];
            for (int i = 0; i < w; i++)//垂直方向
            {
                for (int j = 0; j < h; j++)
                {
                    tempCom4[j] = tempCom1[j * w + i];
                }
                tempCom5 = FFT(tempCom4, h);
                for (int j = 0; j < h; j++)
                {
                    tempCom1[j * w + i] = tempCom5[j];
                }
            }
            return tempCom1;
        }
        /// <summary>
        /// 图像FFT幅度图函数
        /// </summary>
        /// <returns></returns>
        public WriteableBitmap FFTImage()
        {
            WriteableBitmap grayImage = new WriteableBitmap(w, h);
            byte[] temp = srcImage.PixelBuffer.ToArray();
            imageData = new byte[w * h];
            byte tempByte = 0;
            for (int j = 0; j < h; j++)
            {
                for (int i = 0; i < w; i++)
                {
                    tempByte = (byte)((int)(temp[i * 4 + j * w * 4] * 0.114 + temp[i * 4 + 1 + j * w * 4] * 0.587 + temp[i * 4 + 2 + j * w * 4] * 0.299));
                    imageData[i + j * w] = tempByte;
                }
            }
            int bytes = w * h;
            Complex[] freDom = new Complex[bytes];
            double[] tempArray = new double[bytes];
            freDom = FFT2(imageData, true);
            for (int i = 0; i < bytes; i++)
            {
                tempArray[i] = Math.Log(1 + freDom[i].Abs(), 2);
            }
            //灰度级拉伸
            double a = 1000.0, b = 0.0;
            double p;
            for (int i = 0; i < bytes; i++)
            {
                if (a > tempArray[i])
                {
                    a = tempArray[i];
                }
                if (b < tempArray[i])
                {
                    b = tempArray[i];
                }
            }
            p = 255.0 / (b - a);
            for (int i = 0; i < bytes; i++)
            {
                imageData[i] = (byte)(p * (tempArray[i] - a) + 0.5);
            }
            byte[] dstData = new byte[w * h * 4];
            for (int j = 0; j < h; j++)
            {
                for (int i = 0; i < w; i++)
                {
                    dstData[i * 4 + j * w * 4] = (byte)imageData[i + j * w];
                    dstData[i * 4 + 1 + j * w * 4] = (byte)imageData[i + j * w];
                    dstData[i * 4 + 2 + j * w * 4] = (byte)imageData[i + j * w];
                }
            }
            Stream sTemp = grayImage.PixelBuffer.AsStream();
            sTemp.Seek(0, SeekOrigin.Begin);
            sTemp.Write(dstData, 0, w * 4 * h);
            return grayImage;
        }
        /// <summary>
        /// 图像FFT相位图函数
        /// </summary>
        /// <returns></returns>
        public WriteableBitmap FFTPhaseImage()
        {
            WriteableBitmap grayImage = new WriteableBitmap(w, h);
            byte[] temp = srcImage.PixelBuffer.ToArray();
            imageData = new byte[w * h];
            byte tempByte = 0;
            for (int j = 0; j < h; j++)
            {
                for (int i = 0; i < w; i++)
                {
                    tempByte = (byte)((int)(temp[i * 4 + j * w * 4] * 0.114 + temp[i * 4 + 1 + j * w * 4] * 0.587 + temp[i * 4 + 2 + j * w * 4] * 0.299));
                    imageData[i + j * w] = tempByte;
                }
            }
            int bytes = w * h;
            Complex[] freDom = new Complex[bytes];
            double[] tempArray = new double[bytes];
            freDom = FFT2(imageData, true);
            for (int i = 0; i < bytes; i++)
            {
                tempArray[i] = freDom[i].Angle() + 2 * Math.PI;
            }
            //灰度级拉伸
            double a = 1000.0, b = 0.0;
            double p;
            for (int i = 0; i < bytes; i++)
            {
                if (a > tempArray[i])
                {
                    a = tempArray[i];
                }
                if (b < tempArray[i])
                {
                    b = tempArray[i];
                }
            }
            p = 255.0 / (b - a);
            for (int i = 0; i < bytes; i++)
            {
                imageData[i] = (byte)(p * (tempArray[i] - a) + 0.5);
            }
            byte[] dstData = new byte[w * h * 4];
            for (int j = 0; j < h; j++)
            {
                for (int i = 0; i < w; i++)
                {
                    dstData[i * 4 + j * w * 4] = (byte)imageData[i + j * w];
                    dstData[i * 4 + 1 + j * w * 4] = (byte)imageData[i + j * w];
                    dstData[i * 4 + 2 + j * w * 4] = (byte)imageData[i + j * w];
                }
            }
            Stream sTemp = grayImage.PixelBuffer.AsStream();
            sTemp.Seek(0, SeekOrigin.Begin);
            sTemp.Write(dstData, 0, w * 4 * h);
            return grayImage;
        }
    }
}
Win8 Metro(C#)数字图像处理--2.53图像傅立叶变换