原文: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图像傅立叶变换的更多相关文章

  1. Win8 Metro(C#)数字图像处理--3.2图像方差计算

    原文:Win8 Metro(C#)数字图像处理--3.2图像方差计算 /// <summary> /// /// </summary>Variance computing. / ...

  2. Win8 Metro(C#)数字图像处理--3.3图像直方图计算

    原文:Win8 Metro(C#)数字图像处理--3.3图像直方图计算 /// <summary> /// Get the array of histrgram. /// </sum ...

  3. Win8 Metro(C#)数字图像处理--3.4图像信息熵计算

    原文:Win8 Metro(C#)数字图像处理--3.4图像信息熵计算 [函数代码] /// <summary> /// Entropy of one image. /// </su ...

  4. Win8 Metro(C#)数字图像处理--3.5图像形心计算

    原文:Win8 Metro(C#)数字图像处理--3.5图像形心计算 /// <summary> /// Get the center of the object in an image. ...

  5. Win8 Metro(C#)数字图像处理--3.1图像均值计算

    原文:Win8 Metro(C#)数字图像处理--3.1图像均值计算 /// <summary> /// Mean value computing. /// </summary> ...

  6. Win8 Metro(C#)数字图像处理--2.74图像凸包计算

    原文:Win8 Metro(C#)数字图像处理--2.74图像凸包计算 /// <summary> /// Convex Hull compute. /// </summary> ...

  7. Win8 Metro(C#)数字图像处理--2.68图像最小值滤波器

    原文:Win8 Metro(C#)数字图像处理--2.68图像最小值滤波器 /// <summary> /// Min value filter. /// </summary> ...

  8. Win8 Metro(C#)数字图像处理--2.52图像K均值聚类

    原文:Win8 Metro(C#)数字图像处理--2.52图像K均值聚类  [函数名称]   图像KMeans聚类      KMeansCluster(WriteableBitmap src,i ...

  9. Win8 Metro(C#)数字图像处理--2.45图像雾化效果算法

    原文:Win8 Metro(C#)数字图像处理--2.45图像雾化效果算法 [函数名称]   图像雾化         AtomizationProcess(WriteableBitmap src,i ...

随机推荐

  1. 【codeforces 754D】Fedor and coupons

    time limit per test4 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  2. C语言实现使用动态数组来构造栈结构

    我在面前一篇博客<C语言实现使用静态数组来构造栈结构>中使用了静态数组来模拟栈的操作.静态数组的大小是在代码中写死的.是存储在用户栈上面的,使用起来不灵活.在这篇博客中我会使用动态数组来构 ...

  3. amazeui时间组件测试

    amazeui时间组件测试 一.总结 一句话总结: 1.图标是字体样式:input右侧的字体图标是字体样式,所以要引入字体文件,随便找一个项目把里面的字体文件弄过来就ok了 2.多看官方文档:这个时间 ...

  4. 短文评估【安徽省选2003】- hash / trie

    题目分析 其实是hash/trie裸题,讲一下hash的做法:如果其小写状态是第一次出现则加入集合,同时将小写状态加入小写单词的hash表,最后查时查出出现次数即可. code #include< ...

  5. Cocos2d-x 脚本语言Lua基本语法

    Cocos2d-x 脚本语言Lua基本语法 前面一篇博客对Lua这门小巧的语言进行了简单的介绍.本篇博客来给大家略微讲一下Lua的语法.不会长篇累牍得把Lua的全部语法都讲一遍,这里通过下面几点来讲L ...

  6. 【noip模拟】Fancy Signal Translate (暴力 + 哈希)

    题目描述 FST是一名可怜的 OIer,他很强,但是经常 fst,所以 rating 一直低迷. 但是重点在于,他真的很强!他发明了一种奇特的加密方式,这种加密方式只有OIer才能破解. 这种加密方式 ...

  7. scala 主从构造器

    package cn.scala_base.oop.scalaclass /** * 构造器分为两种,一种是主构造器,另一种是从构造器,所有的从构造器必须在其方法体 * 的第一行调用主构造器 * * ...

  8. TensorFlow 实战(三)—— 实现常见公式

    tf.reduce_mean (求向量的均值)等价于 1N∑i=1Nxi 1. 对权值矩阵进行 l2 正则 def variable_with_weight_loss(shape, stddev, w ...

  9. WPF 获得当前输入法语言区域

    原文:WPF 获得当前输入法语言区域 本文告诉大家如何获得 WPF 输入法的语言区域 需要使用 user32 的方法,很简单,请看下面 [DllImport("user32.dll" ...

  10. jQuery分离构造器

    http://www.imooc.com/code/3401 通过new操作符构建一个对象,一般经过四步: A.创建一个新对象   B.将构造函数的作用域赋给新对象(所以this就指向了这个新对象) ...