原文: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;
}
}
}


最新文章

  1. mina-http之坑
  2. js自调用匿名函数的三种写法
  3. 【Openlayers3】在地图上添加highcharts图表
  4. HDFS数据迁移解决方案之DistCp工具的巧妙使用
  5. http://blinkfox.com/shi-yong-spring-aoplai-tong-ji-fang-fa-de-zhi-xing-shi-jian/
  6. C语言:十进制进制转换为其他进制(思想:查表法)
  7. 基本上,把switch,用设计模式代替,肯定是bug和过度设计。想想,本来修改一个文件几行代码可以解决的问题,变成修改3-6个类才能实现一样的功能。不是傻是什么?
  8. android .9文件的一点处理
  9. [置顶] css3 befor after 简单使用 制作时尚焦点图相框
  10. 《类型编程晋级——shapeless类库使用指南》前言及第一章翻译
  11. Example006为弹出窗口加入关闭按钮
  12. 分享一个二维码图片识别控制台程序Demo
  13. xamarin android网络请求总结
  14. C# xml序列化与反序列化 特性的使用
  15. Spotlight&#160;on&#160;Mysql在Windows平台下的安装及使用简介
  16. 最流行的Python编辑器/IDEs你认识吗?
  17. 《Linux内核分析》第五周学习笔记
  18. SharePoint 2007 页面及用户控件
  19. UUID的意义和作用
  20. Hive错误:Permission denied: user=anonymous, access=EXECUTE, inode=”/tmp”

热门文章

  1. 从 BM 到 RBM
  2. hdu 1558 Segment set (并查集)
  3. [NativeScript] Create new application and run emulator
  4. js进阶 10-5 jquery中的层级选择器有哪些
  5. 【BZOJ 1007】 [HNOI2008]水平可见直线
  6. Asp.net压缩网站中的文件
  7. Light libraries是一组通用的C基础库,目标是为减少重复造轮子而写(全部用POSIX C实现)
  8. 贝叶斯推理(Bayes Reasoning)、独立与因式分解
  9. 简明Python3教程 6.基础
  10. C#更改控制台文本的前景色和背景色