/// <summary> /// Maak van een Fourier resultset opnieuw een afbeelding /// </summary> /// <param name="fourier">De Fourier set</param> /// <returns>De geproduceerde grijs-waarden afbeelding</returns> public static Bitmap backwardFFT(ComplexGetal[,] fourier) { float[,] greyscale = new float[fourier.GetLength(0),fourier.GetLength(1)]; fourier = FFT2D(fourier, FourierDirection.Backward); for (int i = 0; i < fourier.GetLength(0); i++) { for (int j = 0; j < fourier.GetLength(1); j++) { greyscale[i, j] = fourier[i, j].Modulus; } } return createImage(greyscale, 1); }
/// <summary> /// Hersorteer de meegegeven Fourier resultatenset van een indeling met de oorsprong in 0,0 /// O - - ---> /// |1,1 1,2 .. /// |2,1 2,2 .. /// |.. .. /// V /// /// Naar een met de oorsprong in het midden /// /// ^ /// 1,-2 1,-1 | 1,1 1,2 /// - - O - - ---> /// -1,-2 -1,-1 | -1,1 -1,2 /// V /// /// Referentie https://www.youtube.com/watch?v=X53SrMnu91A /// </summary> /// <param name="result">Te herindelen set</param> /// <returns>aangepaste set</returns> private static ComplexGetal[,] shiftFFTResult(ComplexGetal[,] result) { int a = result.GetLength(0); int b = result.GetLength(1); ComplexGetal[,] shiftResult = new ComplexGetal[a, b]; for (int i = 0; i < (a / 2); i++) { for (int j = 0; j < (b / 2); j++) { shiftResult[i + (a / 2), j + (b / 2)] = result[i, j]; shiftResult[i + (a / 2), j] = result[i, j + (b / 2)]; shiftResult[i, j + (b / 2)] = result[i + (a / 2), j]; shiftResult[i, j] = result[i + (a / 2), j + (b / 2)]; } } return shiftResult; }
/// <summary> /// Maak een fase plot aan de hand van het Imaginair argument /// </summary> /// <param name="array">Fourier resultset</param> /// <param name="scale">Herschaling van de fase plot</param> /// <returns>Bitmap</returns> private static Bitmap plotArg(ComplexGetal[,] array, int scale) { float[,] argumentPlot = new float[array.GetLength(0), array.GetLength(1)]; float max = 0; // Plaats het argument van ieder complex getal in een multidimensionale float array // Het argument wordt berekend door de ComplexGetal klasse. for (int i = 0; i < array.GetLength(0); i++) { for (int j = 0; j < array.GetLength(1); j++) { argumentPlot[i, j] = (float)Math.Log(1 + Math.Abs(array[i, j].Argument)); // Bepaal de hoogste waarde if (argumentPlot[i, j] > max) max = argumentPlot[i, j]; } } // Herschaal alle waarden met als referentie de hoogste waarde (100%) for (int i = 0; i < argumentPlot.GetLength(0); i++) { for (int j = 0; j < argumentPlot.GetLength(1); j++) { argumentPlot[i, j] = argumentPlot[i, j] / max; } } return createImage(argumentPlot, scale); }
/// <summary> /// Maak een amplitude plot aan de hand van de modulus van de imaginaire getallen /// </summary> /// <param name="array">Fourier resultset</param> /// <param name="scale">Herschaling van de amplitude plot</param> /// <returns>Bitmap</returns> private static Bitmap plotMod(ComplexGetal[,] array, int scale) { float[,] modulusPlot = new float[array.GetLength(0),array.GetLength(1)]; float max = 0; // Plaats de Modulus van ieder complex getal in een multidimensionale float array // De Modulus wordt berekend door de ComplexGetal klasse. for (int i = 0; i < array.GetLength(0); i++) { for (int j = 0; j < array.GetLength(1); j++) { modulusPlot[i, j] = (float)Math.Log(1 + array[i, j].Modulus); // Bepaal de hoogste waarde if (modulusPlot[i, j] > max) max = modulusPlot[i, j]; } } // Herschaal alle waarden met als referentie de hoogste waarde (100%) for (int i = 0; i < modulusPlot.GetLength(0); i++) { for (int j = 0; j < modulusPlot.GetLength(1); j++) { modulusPlot[i, j] /= max; } } return createImage(modulusPlot, scale); }
/// <summary> /// Voert een 2 dimensionale Fourier analyse uit op een afbeelding /// </summary> /// <param name="invoer">De complexe waarden van de afbeelding</param> /// <param name="dir">FourierDirection.Forward or FourierDirection.Backward</param> /// <returns>Fourier resultset</returns> private static ComplexGetal[,] FFT2D(ComplexGetal[,] invoer, FourierDirection dir) { float[] reëel = new float[invoer.GetLength(1)]; float[] imaginair = new float[invoer.GetLength(1)]; ComplexGetal[,] resultaat = invoer; //rijen for (int i = 0; i < invoer.GetLength(0); i++) { // Plaats de waarden in een 1 dimensionale array for (int j = 0; j < invoer.GetLength(1); j++) { reëel[j] = invoer[i, j].Reëel; imaginair[j] = invoer[i, j].Imaginair; } // Voer een 1 dimensionale fourier analyse uit op de huidige rij FFT1D(dir, reëel, imaginair); // Plaats de waarden in het resultaat object for (int j = 0; j < resultaat.GetLength(1); j++) { resultaat[i, j].Reëel = reëel[j]; resultaat[i, j].Imaginair = imaginair[j]; } } //kolommen - gebruik nu het resultaat object, anders gaan de berekeningen van de rijen verloren for (int i = 0; i < resultaat.GetLength(1); i++) { // Plaats de waarden in een 1 dimensionale array for (int j = 0; j < resultaat.GetLength(0); j++) { reëel[j] = resultaat[j, i].Reëel; imaginair[j] = resultaat[j, i].Imaginair; } // Voer een 1 dimensionale fourier analyse uit op de huidige kolom FFT1D(dir, reëel, imaginair); // Plaats de waarden in het resultaat object for (int j = 0; j < resultaat.GetLength(0); j++) { resultaat[j, i].Reëel = reëel[j]; resultaat[j, i].Imaginair = imaginair[j]; } } return resultaat; }