# 【已解决】C# 傅里叶变换

C# 2143浏览
C# 傅里叶变换

c# – 离散傅里叶变换 – 代码日志

AForge.NET/ComplexImage.cs at master · andrewkirillov/AForge.NET
https://github.com/andrewkirillov/AForge.NET/blob/master/Sources/Imaging/ComplexImage.cs
AForge.NET/FourierTransform.cs at master · andrewkirillov/AForge.NET
https://github.com/andrewkirillov/AForge.NET/blob/master/Sources/Math/FourierTransform.cs

 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# fourier transform code
signal processing – An implementation of the fast Fourier transform (FFT) in C# – Stack Overflow

AForge.NET/FourierTransform.cs at master · andrewkirillov/AForge.NET · GitHub
https://github.com/andrewkirillov/AForge.NET/blob/master/Sources/Math/FourierTransform.cs

AForge.NET/ComplexImage.cs at master · andrewkirillov/AForge.NET · GitHub
https://github.com/andrewkirillov/AForge.NET/blob/master/Sources/Imaging/ComplexImage.cs

FFTLibrary 在 C# 中 用于 Visual Studio 2015

Application_Note_ChrisOakley.pdf
Fast Fourier transform – Rosetta Code

A very simple Discrete Fourier Transform algorithm (not suitable for real-time processing) · 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)

```        /// <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++;
}```

```[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}```

`            Tuple<double[], double[]> output = crifanDFT.DFT(input,  partials:input.Length);`

```        /// <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);
}```

`            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 };`

```[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}```

【总结】

`[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]`

crifanDFT.cs
```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;
}
}
}```

```            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++;
}
}```

```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}```

84 queries in 0.165 seconds, using 22.21MB memory