C# 傅里叶变换
AForge.NET/ComplexImage.cs at master · andrewkirillov/AForge.NET
AForge.NET/FourierTransform.cs at master · andrewkirillov/AForge.NET
抽空去试试这个源码
是C语言实现的
感觉不错,抽空去试试
别人给出了数据计算后的例子
目的: 做傅里叶变换, 得到T在各个频率上的振幅
原先数据:
new_Signal = x^2 + y^2 =[0.077641, 0.070009, 0.086816, 0.180072, 0.218088, 0.110777,0.067657, 0.108425, 0.13954 , 0.13954 , 0.195336, 0.165397,0.146461, 0.107648, 0.056641, 0.135629] |
傅里叶变换后是:
FreqAmp = [ 2.005677 +0.j , -0.1811103 +0.01788887j, -0.22535551-0.22328895j, -0.00423924+0.23675752j, 0.17528 +0.161549j , 0.04949067-0.04438796j, -0.06938049+0.09241905j, -0.11173713+0.02325139j, -0.029317 +0.j , -0.11173713-0.02325139j, -0.06938049-0.09241905j, 0.04949067+0.04438796j, 0.17528 -0.161549j , -0.00423924-0.23675752j, -0.22535551+0.22328895j, -0.1811103 -0.01788887j] |
现在要去想办法去用C#实现上述的计算结果
c# fourier transform code
可以考虑是试试这个:
具体实现:
AForge.NET/FourierTransform.cs at master · andrewkirillov/AForge.NET · GitHub
使用范例:
AForge.NET/ComplexImage.cs at master · andrewkirillov/AForge.NET · GitHub
不过有微软官网的
去看看
直接贴出源码了
要去搞清楚如何使用
也有直接的代码
结果用:
using System; using System.Numerics; using System; using System.Numerics; namespace FUYI_Client { class crifanFFT { // Fast Fourier Transform in C# /* Performs a Bit Reversal Algorithm on a postive integer * for given number of bits * e.g. 011 with 3 bits is reversed to 110 */ public static int BitReverse(int n, int bits) { int reversedN = n; int count = bits – 1; n >>= 1; while (n > 0) { reversedN = (reversedN << 1) | (n & 1); count–; n >>= 1; } return ((reversedN << count) & ((1 << bits) – 1)); } /* Uses Cooley-Tukey iterative in-place algorithm with radix-2 DIT case * assumes no of points provided are a power of 2 */ public static void FFT(Complex[] buffer) { int bits = (int)Math.Log(buffer.Length, 2); for (int j = 1; j < buffer.Length / 2; j++) { int swapPos = BitReverse(j, bits); var temp = buffer[j]; buffer[j] = buffer[swapPos]; buffer[swapPos] = temp; } for (int N = 2; N <= buffer.Length; N <<= 1) { for (int i = 0; i < buffer.Length; i += N) { for (int k = 0; k < N / 2; k++) { int evenIndex = i + k; int oddIndex = i + k + (N / 2); var even = buffer[evenIndex]; var odd = buffer[oddIndex]; double term = -2 * Math.PI * k / (double)N; Complex exp = new Complex(Math.Cos(term), Math.Sin(term)) * odd; buffer[evenIndex] = even + exp; buffer[oddIndex] = even – exp; } } } } } } private void testFftToolStripMenuItem_Click(object sender, EventArgs e) { Log(“test FFT”); //Complex[] input = { 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0 }; Complex[] input = { 0.077641, 0.070009, 0.086816, 0.180072, 0.218088, 0.110777, 0.067657, 0.108425, 0.13954, 0.13954, 0.195336, 0.165397, 0.146461, 0.107648, 0.056641, 0.135629 }; crifanFFT.FFT(input); Console.WriteLine(“Results:”); foreach (Complex c in input) { Console.WriteLine(c); } } |
测试结果,除了第一个和预期一致,其他都不一样
(2.005677, 0) (-0.0440878098072094, 0.0563375488458987) (-0.0940835140038455, -0.272891535410738) (-0.203768798154086, 0.0126622006202) (-0.087264, 0.046051) (0.0633735877860757, 0.179707364194415) (0.0618915140038455, 0.305360464589262) (-0.0631129798247799, -0.0151972875798867) (-0.0293169999999998, 0) (-0.0631129798247799, 0.0151972875798867) (0.0618915140038455, -0.305360464589262) (0.0633735877860758, -0.179707364194415) (-0.087264, -0.046051) (-0.203768798154086, -0.0126622006202) (-0.0940835140038455, 0.272891535410738) (-0.0440878098072094, -0.0563375488458987) |

所以只能再去换别的写法
然后换成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | / / / <summary> / / / Provides the Discrete Fourier Transform for a real - valued input signal / / / < / summary> / / / <param name = "input" >the signal to transform< / param> / / / <param name = "partials" >the maximum number of partials to calculate. If not value is given it defaults to input / 2 < / param> / / / <returns>The Cos and Sin components of the signal, respectively< / returns> public static Tuple <double[], double[]> DFT(double[] input , int partials = 0 ) { int len = input .Length; double[] cosDFT = new double[ len / 2 + 1 ]; double[] sinDFT = new double[ len / 2 + 1 ]; if (partials = = 0 ) partials = len / 2 ; for ( int n = 0 ; n < = partials; n + + ) { double cos = 0.0 ; double sin = 0.0 ; for ( int i = 0 ; i < len ; i + + ) { cos + = input [i] * Math.Cos( 2 * Math.PI * n / len * i); sin + = input [i] * Math.Sin( 2 * Math.PI * n / len * i); } cosDFT[n] = cos; sinDFT[n] = sin; } return new Tuple <double[], double[]>(cosDFT, sinDFT); } double[] input = { 0.077641 , 0.070009 , 0.086816 , 0.180072 , 0.218088 , 0.110777 , 0.067657 , 0.108425 , 0.13954 , 0.13954 , 0.195336 , 0.165397 , 0.146461 , 0.107648 , 0.056641 , 0.135629 }; Tuple <double[], double[]> output = crifanDFT.DFT( input ); double[] outputList1 = output.Item1; double[] outputList2 = output.Item2; Console.WriteLine( "Results:" ); int curIdx = 0 ; foreach (double curItem1Value in outputList1) { Console.WriteLine( "[{0}]={{{1}, {2}}}" , curIdx, curItem1Value, outputList2[curIdx]); curIdx + + ; } |
结果竟然是:
计算的结果:
1 2 3 4 5 6 7 8 9 | [0]={2.005677, 0} [1]={-0.181110302258433, -0.0178888702258191} [2]={-0.225355514003845, 0.223288954424222} [3]={-0.00423923852817759, -0.236757522000121} [4]={0.175279999999999, -0.161549} [5]={0.0494906709200072, 0.0443879571855055} [6]={-0.0693804859961551, -0.092419045575778} [7]={-0.111737130133397, -0.0232513910401929} [8]={-0.029317, 8.53570355076414E-16} |
是和预期的,基本一致,除了最后一个
但是16个输入的值
输出的tuple,用于表示复数,竟然只有10个了:

很是奇怪,所以要去找找原因
去调试,才看清,原来默认只计算length/2的个数

所以传入原始数组长度,再去计算看看结果是否完全符合预期
1 | Tuple<double[], double[]> output = crifanDFT.DFT(input, partials:input.Length); |
结果:
内部报错

原来是cos和sin的数组长度也不对,没有变回来传入的长度
所以去改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | / / / <summary> / / / Provides the Discrete Fourier Transform for a real - valued input signal / / / < / summary> / / / <param name = "input" >the signal to transform< / param> / / / <param name = "partials" >the maximum number of partials to calculate. If not value is given it defaults to input / 2 < / param> / / / <returns>The Cos and Sin components of the signal, respectively< / returns> public static Tuple <double[], double[]> DFT(double[] input , int partials = 0 ) { int len = input .Length; if (partials = = 0 ) partials = len / 2 ; / / double[] cosDFT = new double[ len / 2 + 1 ]; / / double[] sinDFT = new double[ len / 2 + 1 ]; double[] cosDFT = new double[partials]; double[] sinDFT = new double[partials]; / / if (partials = = 0 ) / / partials = len / 2 ; / / for ( int n = 0 ; n < = partials; n + + ) for ( int n = 0 ; n < partials; n + + ) { double cos = 0.0 ; double sin = 0.0 ; for ( int i = 0 ; i < len ; i + + ) { cos + = input [i] * Math.Cos( 2 * Math.PI * n / len * i); sin + = input [i] * Math.Sin( 2 * Math.PI * n / len * i); } cosDFT[n] = cos; sinDFT[n] = sin; } return new Tuple <double[], double[]>(cosDFT, sinDFT); } |
结果:
是可以输出我们希望的结果的

输入:
1 | double[] input = { 0.077641, 0.070009, 0.086816, 0.180072, 0.218088, 0.110777, 0.067657, 0.108425, 0.13954, 0.13954, 0.195336, 0.165397, 0.146461, 0.107648, 0.056641, 0.135629 }; |
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | [0]={2.005677, 0} [1]={-0.181110302258433, -0.0178888702258191} [2]={-0.225355514003845, 0.223288954424222} [3]={-0.00423923852817759, -0.236757522000121} [4]={0.175279999999999, -0.161549} [5]={0.0494906709200072, 0.0443879571855055} [6]={-0.0693804859961551, -0.092419045575778} [7]={-0.111737130133397, -0.0232513910401929} [8]={-0.029317, 8.53570355076414E-16} [9]={-0.111737130133397, 0.0232513910401936} [10]={-0.0693804859961542, 0.092419045575779} [11]={0.0494906709200082, -0.0443879571855054} [12]={0.175279999999999, 0.161549} [13]={-0.0042392385281777, 0.236757522000121} [14]={-0.225355514003845, -0.223288954424222} [15]={-0.181110302258429, 0.0178888702258207} |
对比后发现是我们要的

【总结】
目前,对于数据:
输入:
1 | [0.077641, 0.070009, 0.086816, 0.180072, 0.218088, 0.110777,0.067657, 0.108425, 0.13954 , 0.13954 , 0.195336, 0.165397,0.146461, 0.107648, 0.056641, 0.135629] |
可以通过C#代码:
crifanDFT.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | using System; using System.Numerics; namespace FUYI_Client { class crifanDFT { / / Fast Fourier Transform in C # / / / <summary> / / / Provides the Discrete Fourier Transform for a real - valued input signal / / / < / summary> / / / <param name = "input" >the signal to transform< / param> / / / <param name = "partials" >the maximum number of partials to calculate. If not value is given it defaults to input / 2 < / param> / / / <returns>The Cos and Sin components of the signal, respectively< / returns> public static Tuple <double[], double[]> DFT(double[] input , int partials = 0 ) { int len = input .Length; if (partials = = 0 ) partials = len / 2 ; / / double[] cosDFT = new double[ len / 2 + 1 ]; / / double[] sinDFT = new double[ len / 2 + 1 ]; double[] cosDFT = new double[partials]; double[] sinDFT = new double[partials]; / / if (partials = = 0 ) / / partials = len / 2 ; / / for ( int n = 0 ; n < = partials; n + + ) for ( int n = 0 ; n < partials; n + + ) { double cos = 0.0 ; double sin = 0.0 ; for ( int i = 0 ; i < len ; i + + ) { cos + = input [i] * Math.Cos( 2 * Math.PI * n / len * i); sin + = input [i] * Math.Sin( 2 * Math.PI * n / len * i); } cosDFT[n] = cos; sinDFT[n] = sin; } return new Tuple <double[], double[]>(cosDFT, sinDFT); } / / / <summary> / / / Takes the real - valued Cos and Sin components of Fourier transformed signal and reconstructs the time - domain signal / / / < / summary> / / / <param name = "cos" >Array of cos components, containing frequency components from 0 to pi. sin.Length must match cos.Length< / param> / / / <param name = "sin" >Array of sin components, containing frequency components from 0 to pi. sin.Length must match cos.Length< / param> / / / <param name = "len" > / / / The length of the output signal. / / / If len < (partials - 1 ) * 2 then frequency data will be lost in the output signal. / / / if no len parameter is given it defaults to (partials - 1 ) * 2 / / / < / param> / / / <returns>the real - valued time - domain signal< / returns> public static double[] IDFT(double[] cos, double[] sin, int len = 0 ) { if (cos.Length ! = sin.Length) throw new ArgumentException( "cos.Length and sin.Length bust match!" ); if ( len = = 0 ) len = (cos.Length - 1 ) * 2 ; double[] output = new double[ len ]; int partials = sin.Length; if (partials > len / 2 ) partials = len / 2 ; for ( int n = 0 ; n < = partials; n + + ) { for ( int i = 0 ; i < len ; i + + ) { output[i] + = Math.Cos( 2 * Math.PI * n / len * i) * cos[n]; output[i] + = Math.Sin( 2 * Math.PI * n / len * i) * sin[n]; } } return output; } } } |
注:此处暂时没用到IDFT,以备后用
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | double[] input = { 0.077641 , 0.070009 , 0.086816 , 0.180072 , 0.218088 , 0.110777 , 0.067657 , 0.108425 , 0.13954 , 0.13954 , 0.195336 , 0.165397 , 0.146461 , 0.107648 , 0.056641 , 0.135629 }; / / Tuple <double[], double[]> output = crifanDFT.DFT( input ); Tuple <double[], double[]> output = crifanDFT.DFT( input , partials: input .Length); double[] outputList1 = output.Item1; double[] outputList2 = output.Item2; Console.WriteLine( "Results:" ); int curIdx = 0 ; foreach (double curItem1Value in outputList1) { Console.WriteLine( "[{0}]={{{1}, {2}}}" , curIdx, curItem1Value, outputList2[curIdx]); curIdx + + ; } } |
可以输出我们要的结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Results: [0]={2.005677, 0} [1]={-0.181110302258433, -0.0178888702258191} [2]={-0.225355514003845, 0.223288954424222} [3]={-0.00423923852817759, -0.236757522000121} [4]={0.175279999999999, -0.161549} [5]={0.0494906709200072, 0.0443879571855055} [6]={-0.0693804859961551, -0.092419045575778} [7]={-0.111737130133397, -0.0232513910401929} [8]={-0.029317, 8.53570355076414E-16} [9]={-0.111737130133397, 0.0232513910401936} [10]={-0.0693804859961542, 0.092419045575779} [11]={0.0494906709200082, -0.0443879571855054} [12]={0.175279999999999, 0.161549} [13]={-0.0042392385281777, 0.236757522000121} [14]={-0.225355514003845, -0.223288954424222} [15]={-0.181110302258429, 0.0178888702258207} |
转载请注明:在路上 » 【已解决】C# 傅里叶变换