原文: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. [Compose] Isomorphisms and round trip data transformations

    What is Isomorphisms?We have a value x, then apply function 'to' and 'from' to value 'x', the result ...

  2. 【u025】贝茜的晨练计划

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 奶牛们打算通过锻炼来培养自己的运动细胞,作为其中的一员,贝茜选择的运动方式是每天进行N(1 <= ...

  3. 算法 Tricks(五)—— 二进制逻辑运算

    int flag = 1; while ( (data & flag) == 0 ) flag <<= 1; 判断某数的二进制形式的某位(第 k 位)是否为 1,将其与 2k 相与 ...

  4. [转]Redis 与Mysql通信

    http://blog.csdn.net/hpb21/article/details/7852934 找了点资料看了下.学习心得如下: 1 Mysql更新Redis Mysql更新Redis借鉴mem ...

  5. 带你轻松看源代码---AsyncTask(异步任务)

    本文出自博客Vander丶CSDN博客,如需转载请标明出处,尊重原创谢谢 博客地址:http://blog.csdn.net/l540675759/article/details/62893318 写 ...

  6. 关于iPhone开发的一些建议

    建议 以后的应用程序,都使用AutoLayout, 不要再用绝对定位CGReck. 使用类似网页的方式来设计界面. 设计师好,程序员也好,尽量使用点这个单位进行思考,而不要使用像素.比如,你需要做44 ...

  7. centos 软件安装的三种方式

    Linux下面安装软件的常见方法: 1.yum 替你下载软件 替你安装 替你解决依赖关系 点外卖 缺少的东西 外卖解决 1).方便 简单2)没有办法深入修改 yum install -y tree 2 ...

  8. 项目流程管理&amp;&amp;架构总结

    1 项目背景 所在业务在早期没有营销费用,买家购买商品的折扣优惠是由卖家提供的.全部订单的终于价格是由卖家和业务方确定的,整个购买流程非常easy. 如今此业务收受到公司重视,业务团队能申请到营销费用 ...

  9. 华为云软件开发云:容器DevOps,原来如此简单!

    当开发团队把代码提交到 Git 应用仓库的那一刻,他们心里在想什么? 祈祷没有bug?渴望回家补觉?产品经理Go Die? 对,也不对.因为这只是最终发布万里长征的一小步,接下来要面对测试环境.生产环 ...

  10. 世界卫生组织(WHO)发出最新警告:埃博拉疫情应急响应

    10月14r日.世界卫生组织(WHO)发出警告:在未来两个月内,西非国家将面对"could face up to 10 thousand new Ebola cases a week wit ...