/// <summary> /// Applies convolution matrix/kernel to image. /// i.e. edge detection. /// </summary> /// <param name="bitmap">Image to apply kernel to</param> /// <param name="convolutionType">Type of convolution</param> /// <returns>Bitmap with kernel applied</returns> public static Bitmap ApplyKernel(Bitmap bitmap, ConvolutionType convolutionType) { // Get convolution kernel to apply int[,] matrix = convolutionType.GetConvolutionMatrix(); return(ApplyKernel(bitmap, matrix)); }
// This algorithm is derived from Table 6-1 of ISBN 0-9660176-3-3 "The Scientist and Engineer's Guide to Digital Signal Processing" // http://www.dspguide.com/ch6/3.htm public List <double> Convolve(List <double> kernel, List <double> input, ConvolutionType type) { if (type == ConvolutionType.INPUTSIDE) { return(InputSideConvolution(kernel, input)); } else { return(OuputSideConvolution(kernel, input)); } }
/// <summary> /// Gets the description associated with the enum value. /// </summary> /// <param name="type">ConvolutionType value</param> /// <returns>enum description as string</returns> public static string GetDescription(this ConvolutionType type) { // Query enum for info FieldInfo fi = type.GetType().GetField(type.ToString()); if (fi != null) { // Get first description attribute DescriptionAttribute attr = ((DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false)).FirstOrDefault(); // Get description value (default to enum string if missing) return(attr?.Description ?? type.ToString()); } return(type.ToString()); }
public void TestGetConvolutionMatrix() { ConvolutionType type = ConvolutionType.Smoothing; // 2D matrix int[,] matrix = type.GetConvolutionMatrix(); for (int i = 0; i < matrix.GetLength(0); i++) { for (int j = 0; j < matrix.GetLength(1); j++) { // Smoothing filter contains all 1's Assert.AreEqual(1, matrix.GetValue(i, j)); } } }
/// <summary> /// Applies convolution matrix/kernel to image. /// </summary> /// <typeparam name="T">Image type to process and return</typeparam> /// <param name="image">Image to apply kernel to</param> /// <param name="convolutionType">Type of convolution</param> /// <returns>Image with kernel applied</returns> public static T ApplyKernel <T>(T image, ConvolutionType convolutionType) where T : Image { return(ApplyKernel(image, convolutionType.GetConvolutionMatrix())); }
/// <summary> /// Gets matrix/kernel for convolution. /// </summary> /// <param name="convolutionType">Type of convolution</param> /// <returns>2D matrix of kernel values</returns> public static int[,] GetConvolutionMatrix(this ConvolutionType convolutionType) { switch (convolutionType) { // Use Laplacian as default edge detection/sharpen filter case ConvolutionType.Edge: case ConvolutionType.Sharpen: case ConvolutionType.EdgeLaplacianWithPeak4: return(new int[3, 3] { { 0, -1, 0 }, { -1, 4, -1 }, { 0, -1, 0 } }); case ConvolutionType.EdgeLaplacianWithPeak8: return(new int[3, 3] { { -1, -1, -1 }, { -1, 8, -1 }, { -1, -1, -1 } }); case ConvolutionType.EdgeSobelHorizontal: return(new int[3, 3] { { 1, 2, 1 }, { 0, 0, 0 }, { -1, -2, -1 } }); case ConvolutionType.EdgeSobelVertical: return(new int[3, 3] { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } }); case ConvolutionType.Smoothing: case ConvolutionType.NoiseReduction: return(new int[3, 3] { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } }); case ConvolutionType.SmoothingWithHighPeak: return(new int[3, 3] { { 1, 3, 1 }, { 3, 16, 3 }, { 1, 3, 1 } }); case ConvolutionType.SmoothingMexicanHat: return(new int[3, 3] { { 1, 2, 1 }, { 2, 4, 2 }, { 1, 2, 1 } }); case ConvolutionType.Emboss: return(new int[3, 3] { { -2, -1, 0 }, { -1, 1, 1 }, { 0, 1, 2 } }); case ConvolutionType.EdgeLaplacianOfGaussian: return(new int[9, 9] { { 0, 1, 1, 2, 2, 2, 1, 1, 0 }, { 1, 2, 4, 5, 5, 5, 4, 2, 1 }, { 1, 4, 5, 3, 0, 3, 5, 4, 1 }, { 2, 5, 3, -12, -24, -12, 3, 5, 2 }, { 2, 5, 0, -24, -40, -24, 0, 5, 2 }, { 2, 5, 3, -12, -24, -12, 3, 5, 2 }, { 1, 4, 5, 3, 0, 3, 5, 4, 1 }, { 1, 2, 4, 5, 5, 5, 4, 2, 1 }, { 0, 1, 1, 2, 2, 2, 1, 1, 0 } }); default: throw new NotImplementedException($"Matrix not implemented for {convolutionType}"); } }
public void TestGetDescription(ConvolutionType type, string description) { Assert.AreEqual(type.GetDescription(), description); }