public static byte[,] Sharpen(byte[,] input, int w) { var imageToSharpen = Convolution.Convolve(input, Laplacian3X3, 1); var image = new byte[imageToSharpen.GetLength(0), imageToSharpen.GetLength(1)]; for (var x = 0; x < imageToSharpen.GetLength(0); x++) { for (var y = 0; y < imageToSharpen.GetLength(1); y++) { image[x, y] = (byte)Math.Round(HelperFunctions.ImageClamp(input[x, y] - w * imageToSharpen[x, y])); } } return(image); }
/// <summary> /// Edge detection using 4 Sobel kernels /// </summary> public static byte[,] DetectEdges(byte[,] input) { Console.WriteLine("[Pre-processing] Applying Edge Detection using 4 Sobel kernels..."); var image1 = Convolution.Convolve(input, SobelKernel3X3V, 1); var image2 = Convolution.Convolve(input, SobelKernel3X3H, 1); var midImage1 = new byte[image1.GetLength(0), image1.GetLength(1)]; for (var x = 0; x < midImage1.GetLength(0); x++) { for (var y = 0; y < midImage1.GetLength(1); y++) { var final = Math.Sqrt(image1[x, y] * image1[x, y] + image2[x, y] * image2[x, y]); midImage1[x, y] = (byte)ImageClamp2(Math.Round(final)); } } var image3 = Convolution.Convolve(input, SobelKernel3X3Minv, 1); var image4 = Convolution.Convolve(input, SobelKernel3X3Minh, 1); var midImage2 = new byte[image1.GetLength(0), image1.GetLength(1)]; for (var x = 0; x < midImage2.GetLength(0); x++) { for (var y = 0; y < midImage2.GetLength(1); y++) { var final = Math.Sqrt(image3[x, y] * image3[x, y] + image4[x, y] * image4[x, y]); midImage2[x, y] = (byte)ImageClamp2(Math.Round(final)); } } var finalImage = new byte[image1.GetLength(0), image1.GetLength(1)]; for (var x = 0; x < midImage2.GetLength(0); x++) { for (var y = 0; y < midImage2.GetLength(1); y++) { var final = Math.Sqrt(midImage1[x, y] * midImage1[x, y] + midImage2[x, y] * midImage2[x, y]); finalImage[x, y] = (byte)ImageClamp2(Math.Round(final)); } } return(finalImage); }
/// <summary> /// Perform Canny edge detection /// </summary> public static byte[,] CannyEdgeDetector(byte[,] input, int blur = 1, byte high = 90, byte low = 90) { var copy = BilateralFilter.BilateralFilter2D(input); // Preprocessing before detecting edges // ======================= Adapted Sobel edge detection from earlier implementation ======================= var image1 = Convolution.Convolve(copy, EdgeDetection.SobelKernel3X3V, 1); var image2 = Convolution.Convolve(copy, EdgeDetection.SobelKernel3X3H, 1); var midImage1 = new double[image1.GetLength(0), image1.GetLength(1)]; for (var x = 0; x < midImage1.GetLength(0); x++) { for (var y = 0; y < midImage1.GetLength(1); y++) { var final = Math.Sqrt(image1[x, y] * image1[x, y] + image2[x, y] * image2[x, y]); midImage1[x, y] = (byte)EdgeDetection.ImageClamp2(Math.Round(final)); } } var image3 = Convolution.Convolve(copy, EdgeDetection.SobelKernel3X3Minv, 1); var image4 = Convolution.Convolve(copy, EdgeDetection.SobelKernel3X3Minh, 1); var midImage2 = new double[image1.GetLength(0), image1.GetLength(1)]; for (var x = 0; x < midImage2.GetLength(0); x++) { for (var y = 0; y < midImage2.GetLength(1); y++) { var final = Math.Sqrt(image3[x, y] * image3[x, y] + image4[x, y] * image4[x, y]); midImage2[x, y] = (byte)EdgeDetection.ImageClamp2(Math.Round(final)); } } var imageG = new double[image1.GetLength(0), image1.GetLength(1)]; for (var x = 0; x < midImage2.GetLength(0); x++) { for (var y = 0; y < midImage2.GetLength(1); y++) { var final = midImage1[x, y] + midImage2[x, y];/*Math.Sqrt(midImage1[x, y] * midImage1[x, y] + midImage2[x, y] * midImage2[x, y]);*/ imageG[x, y] = (byte)EdgeDetection.ImageClamp2(Math.Round(final)); } } var imageT = new int[midImage1.GetLength(0), midImage1.GetLength(1)]; for (var x = 0; x < imageT.GetLength(0); x++) { for (var y = 0; y < imageT.GetLength(1); y++) { imageT[x, y] = (int)Math.Round(Math.Atan2(midImage2[x, y], midImage2[x, y]) * (5.0 / Math.PI) + 5) % 5; } } // ======================================================================================================== var suppressed = Suppress(imageG, imageT); //Perform Non-maximum suppression var highEdges = HelperFunctions.ThresholdDouble(suppressed, high); // Keep the strong edges in one map var lowEdges = HelperFunctions.ThresholdDouble(suppressed, low); // Keep weaker edges in another map var highEdgesByte = Double2DtoByte2D(highEdges); var lowEdgesByte = Double2DtoByte2D(lowEdges); var CombinedThresholds = BinaryOperators.ORoperator(highEdgesByte, lowEdgesByte); // Hysteresis to trace edges return(Hysteresis(highEdgesByte, CombinedThresholds)); }