/// <summary> /// Applies the Fast Fourier Transform in 2 dimensions to a Signal in 2 dimensions /// </summary> /// <param name="signal">The Signal2D to apply FFT2D to</param> /// <returns>The Fourier Transform of the Signal2D</returns> public static Signal2D FFT2D(Signal2D signal) { Signal2D result = new Signal2D(signal.Height, signal.Width); for (int i = 0; i < result.Height; i++) { result[i] = new ComplexNumber[signal[i].Length]; } //rows for (int n = 0; n < signal.Height; n++) { result[n] = FFT(signal[n]); } //columns for (int i = 0; i < signal[0].Length; i++) { ComplexNumber[] col = new ComplexNumber[signal.Height]; for (int j = 0; j < col.Length; j++) { col[j] = result[j][i]; } col = FFT(col); for (int j = 0; j < col.Length; j++) { result[j][i] = col[j]; } } return(result); }
/// <summary> /// Gets the Conjugate for each frequency in the Signal2D /// </summary> /// <returns>A new Signal2D containing the Conjugate for each frequency</returns> public Signal2D GetConjugate() { Signal2D result = new Signal2D(Height, Width); for (int i = 0; i < Height; i++) { result[i] = this[i].GetConjugate(); } return(result); }
/// <summary> /// Creates a new Image based on a Signal2D /// </summary> /// <param name="matrix">The Signal2D to base off of</param> public Image(Signal2D matrix) { BMap = new Bitmap(matrix.Width, matrix.Height); for (int i = 0; i < matrix.Height; i++) { for (int j = 0; j < matrix[0].Length; j++) { Set(j, i, Color.FromArgb((int)matrix[i][j].Real)); } } }
/// <summary> /// Multiplies a Signal2D by a scalar /// </summary> /// <param name="a">The Signal2D to multiply</param> /// <param name="scalar">The scalar to multiply</param> /// <returns>The product of the Signal2D and the scalar</returns> public static Signal2D operator*(Signal2D a, ComplexNumber scalar) { Signal2D result = new Signal2D(a.Height, a.Width); for (int y = 0; y < a.Height; y++) { for (int x = 0; x < a.Width; x++) { result[y][x] = a[y][x] * scalar; } } return(result); }
/// <summary> /// Applies the Inverted Fast Fourier Transform algorithm in 2 dimensions to a Signal /// </summary> /// <param name="signal">The Signal2D to apply IFFT2D to</param> /// <returns>The Inverted Fourier Transform of the Signal2D</returns> public static Signal2D InverseFFT2D(Signal2D signal) { Signal2D result = signal.GetConjugate(); result = FFT2D(result); for (int i = 0; i < signal.Height; i++) { for (int j = 0; j < signal.Width; j++) { result[i][j] /= signal.Width * signal.Height; } } return(result); }
/// <summary> /// Deconstructs the Image into 3 Signal2Ds: red, green, and blue /// </summary> /// <returns>A Signal2D array with 3 Signal2Ds for each color</returns> public Signal2D[] Deconstruct() { Signal2D[] rgb = new Signal2D[] { new Signal2D((int)Height, (int)Width), new Signal2D((int)Height, (int)Width), new Signal2D((int)Height, (int)Width) }; for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { rgb[0][i][j] = BMap.GetPixel(i, j).R; rgb[1][i][j] = BMap.GetPixel(i, j).G; rgb[2][i][j] = BMap.GetPixel(i, j).B; } } return(rgb); }
/// <summary> /// Gets all blue values in a Signal2D of the Image /// </summary> /// <returns>The blue values in a Signal2D</returns> public Signal2D GetBlueMatrix() { Signal2D matrix = new Signal2D((int)Height, (int)Width); for (int i = 0; i < Height; i++) { matrix[i] = new Signal(matrix.Width); for (int j = 0; j < Width; j++) { matrix[i][j] = BMap.GetPixel(i, j).B; } } return(matrix); }
/// <summary> /// Subtracts a Signal2D from another /// </summary> /// <param name="a">The first Signal2D</param> /// <param name="b">The second Signal2D</param> /// <returns>The difference of the two Signals</returns> public static Signal2D operator-(Signal2D a, Signal2D b) { if (a.Height != b.Height || a.Width != b.Width) { throw new ArgumentException("Sizes must be equal"); } Signal2D result = new Signal2D(a.Height, a.Width); for (int y = 0; y < a.Height; y++) { for (int x = 0; x < a.Width; x++) { result[y][x] = a[y][x] - b[y][x]; } } return(result); }
/// <summary> /// Reconstructs the Image from 3 Signal2Ds each representing R G or B /// </summary> /// <param name="red">The red signal</param> /// <param name="green">The green signal</param> /// <param name="blue">The blue signal</param> /// <returns>An Image created from the rgb signals</returns> public static Image Reconstruct(Signal2D red, Signal2D green, Signal2D blue) { Image image = new Image(red.Width, red.Height); for (int i = 0; i < image.Height; i++) { for (int j = 0; j < image.Width; j++) { int r = (int)red[i][j].Real; if (red[i][j].Real > 255) { red[i][j] = 255; } if (green[i][j].Real > 255) { green[i][j] = 255; } if (blue[i][j].Real > 255) { blue[i][j] = 255; } if (red[i][j].Real < 0) { red[i][j] = 0; } if (green[i][j].Real < 0) { green[i][j] = 0; } if (blue[i][j].Real < 0) { blue[i][j] = 0; } Color c = Color.FromArgb((int)red[i][j], (int)green[i][j], (int)blue[i][j]); image.Set(i, j, c); } } return(image); }
/// <summary> /// Scales the Signal2D based on the max value between 0-255 /// </summary> /// <returns>A scaled version of the Signal2D</returns> public Signal2D Scale() { Signal2D mag = this; int[] maxIndex = Max(); int[] minIndex = Min(); double max = this[maxIndex[0]][maxIndex[1]].Real; double min = this[minIndex[0]][minIndex[1]].Real; double scalar = 255.0 / max; for (int i = 0; i < mag.Height; i++) { for (int j = 0; j < mag.Width; j++) { mag[i][j] *= scalar; } } maxIndex = Max(); minIndex = Min(); max = this[maxIndex[0]][maxIndex[1]].Real; min = this[minIndex[0]][minIndex[1]].Real; return(mag); }
/// <summary> /// Calculates the cross correlation of 2 dimensional Signals /// </summary> /// <param name="signal">The response Signal</param> /// <param name="pulse">The pulse Signal</param> /// <returns>The cross correlation</returns> public static Signal2D CrossCorrelation2D(Signal2D signal, Signal2D pulse) { return(InverseFFT2D(FFT2D(pulse).GetConjugate() * FFT2D(signal))); }