[函数名称]
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; } } }