/// <summary> /// Apply a function with the signature FrequencyFilterEquation to the real and the imaginary /// components of each complex "pixel" in a ComplexImage. /// </summary> /// <param name="complex">The image to apply the filter to.</param> /// <param name="equation">The equation of the filter.</param> /// <returns>The resulting ComplexImage.</returns> public static ComplexImage ApplyFilter( ComplexImage complex, FrequencyFilterEquation equation) { ComplexImage ret = new ComplexImage(complex); double filter_mult; // Apply equation... for (int u = 0; u < ret.Width; ++u) { for (int v = 0; v < ret.Height; ++v) { filter_mult = equation(u, v); ret[u, v].real *= filter_mult; ret[u, v].imag *= filter_mult; } } return ret; }
// To be implemented by frequency domain filters /// <summary> /// Apply filter to a ComplexImage. Override to implement a filter in frequency domain. /// </summary> /// <param name="complexImg"></param> /// <param name="configs"></param> /// <returns></returns> public abstract ComplexImage ApplyFilter(ComplexImage complexImg, SortedDictionary<string, object> configs);
// Dummy override /// <summary> /// Apply filter to a ComplexImage. This method will throw a NotImplementedException. /// </summary> /// <param name="complexImg"></param> /// <param name="configs"></param> /// <exception cref="NotImplementedException">Spatial Domain Filters do not operate on ComplexImage.</exception> /// <returns></returns> public override ComplexImage ApplyFilter(ComplexImage complexImg, SortedDictionary<string, object> configs) { // Throw exception ... to turn a ComplexImage into bytes, you have to know // which forward-transform and reverse-transform to perform! throw new NotImplementedException("Spatial Domain Filters do not operate on ComplexImage. Apply the inverse transform first!"); }
/// <summary> /// Performs the following tests on the transform instance: /// * checks the size of the data after a transform or a reverse-transform /// * checks the data after a transform or a reverse-transform /// * checks null output ///</summary> ///<remarks> /// Comparision of doubles conformant with the documentation at: http://msdn.microsoft.com/en-us/library/ya2zha7s.aspx ///</remarks> private void TransformTestTestData( TransformCoreBase<ComplexImage> df, int i, double[,] wellKnownData, ComplexImage wellKnownTransform) { // Perform transform ComplexImage calculatedTransform = df.ApplyTransformBase(wellKnownData); // ** Check Reference Assert.IsNotNull(calculatedTransform, "Test #{0}: Generated transform is null :(."); // ** Check Sizes Assert.AreEqual(wellKnownData.GetLength(0), calculatedTransform.Width, "Test #{0}: Width of transform does not match width of original data.", i); Assert.AreEqual(wellKnownData.GetLength(1), calculatedTransform.Height, "Test #{0}: Height of transform does not match width of original data.", i); // ** Check Data int x, y; const double tollerance = 0.0001; for (x = 0; x < wellKnownData.GetLength(0); ++x) { for (y = 0; y < wellKnownData.GetLength(1); ++y) { Assert.AreEqual(wellKnownTransform[x, y].real, calculatedTransform[x, y].real, tollerance, "Test #{0}: Expected {1}, but found {2} in the transform @({3}, {4}).real .", i, wellKnownTransform[x, y].real, calculatedTransform[x, y].real, x, y); Assert.AreEqual(wellKnownTransform[x, y].imag, calculatedTransform[x, y].imag, tollerance, "Test #{0}: Expected {1}, but found {2} in the transform @({3}, {4}).imag .", i, wellKnownTransform[x, y].imag, calculatedTransform[x, y].imag, x, y); } } // Perform reverse-transform double[,] calculatedData = df.ApplyReverseTransformBase(calculatedTransform); // ** Check Reference Assert.IsNotNull(calculatedData, "Test #{0}: Generated reverse-transform is null :(."); // ** Check Sizes Assert.AreEqual(calculatedTransform.Width, calculatedData.GetLength(0), "Width of reverse-transform does not match width of transform."); Assert.AreEqual(calculatedTransform.Height, calculatedData.GetLength(1), "Height of reverse-transform does not match width of transform."); // ** Check Data for (x = 0; x < wellKnownData.GetLength(0); ++x) { for (y = 0; y < wellKnownData.GetLength(1); ++y) { // Be careful with rounding error in the double datatype >:( Assert.AreEqual(wellKnownData[x, y], calculatedData[x, y], tollerance, "Test #{0}: Expected {1}, but found {2} in the reverse-transform @({3}, {4}).", i, wellKnownData[x, y], calculatedData[x, y], x, y); } } }
public FourierForm(ComplexImage complexImage) : this() { _complex = complexImage; }
/// <summary> /// Creates a copy of a ComplexImage. /// </summary> /// <param name="copy">The ComplexImage to copy.</param> public ComplexImage(ComplexImage copy) { int width = copy.Width; int height = copy.Height; _elemns = new Complex[width, height]; for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { _elemns[x, y] = copy[x, y].Clone(); } } }
/// <summary> /// Converts the ComplexImage to a bitmap (for display purposes). /// Is applied a log to the data for better plotting. /// </summary> /// <param name="bitmapType">The type of bitmap to generate.</param> /// <returns>Bitmap representation of the ComplexImage.</returns> public Bitmap ToBitmap(ComplexImageBitmapType bitmapType) { int x, y; int width = this.Width, height = this.Height; Bitmap ret = null; ComplexImage transform = new ComplexImage(this); double[,] logs = new double[width, height]; double[,] data = new double[width, height]; int[,] normalized = new int[width, height]; for (x = 0; x < width; ++x) { for (y = 0; y < height; ++y) { switch (bitmapType) { case ComplexImageBitmapType.Magnitude: data[x, y] = transform[x, y].Magnitude(); logs[x, y] = (float)(Math.Log(0.1 + data[x, y])); break; case ComplexImageBitmapType.Phase: data[x, y] = transform[x, y].Phase(); logs[x, y] = (float)Math.Log(0.1 + Math.Abs(data[x, y])); break; } } } // get max and min double max = double.MinValue, min = double.MaxValue; for (x = 0; x < width; ++x) { for (y = 0; y < height; ++y) { max = Math.Max(max, logs[x, y]); min = Math.Min(min, logs[x, y]); } } double range = max - min; // Normalize data for (x = 0; x < width; ++x) { for (y = 0; y < height; ++y) { //normalized[x, y] = (int)(byte.MaxValue * (logs[x, y] / max)); normalized[x, y] = (int)(byte.MaxValue * ((logs[x, y] - min) / range)); } } // write to bitmap ... ret = Facilities.ToBitmap(normalized); //switch (bitmapType) //{ // case ComplexImageBitmapType.Magnitude: // // divide by max and normalize // for (x = 0; x < width; ++x) // { // for (y = 0; y < height; ++y) // { // //normalized[x, y] = (int)(byte.MaxValue * (logs[x, y] / max)); // normalized[x, y] = (int) (byte.MaxValue * ((logs[x, y] - min) / range)); // } // } // // write to bitmap ... // ret = Facilities.ToBitmap(normalized); // break; // case ComplexImageBitmapType.Phase: // // divide by max and normalize // for (x = 0; x < width; ++x) // { // for (y = 0; y < height; ++y) // { // //normalized[x, y] = (int)(byte.MaxValue * (logs[x, y] / max)); // normalized[x, y] = (int)(byte.MaxValue * ((logs[x, y] - min) / range)); // } // } // // write to bitmap ... // ret = Facilities.ToBitmap(normalized); // break; //} return ret; }