/// <summary> /// Calculate Gradient vector between the given pixel and its right and bottom ones /// </summary> /// <param name="x">pixel x-coordinate</param> /// <param name="y">pixel y-coordinate</param> /// <param name="ImageMatrix">colored image matrix</param> /// <returns></returns> private static Vector2D CalculateGradientAtPixel(int x, int y, RGBPixel[,] ImageMatrix) { Vector2D gradient = new Vector2D(); RGBPixel mainPixel = ImageMatrix[y, x]; double pixelGrayVal = 0.21 * mainPixel.red + 0.72 * mainPixel.green + 0.07 * mainPixel.blue; if (y == GetHeight(ImageMatrix) - 1) { //boundary pixel. for (int i = 0; i < 3; i++) { gradient.Y = 0; } } else { RGBPixel downPixel = ImageMatrix[y + 1, x]; double downPixelGrayVal = 0.21 * downPixel.red + 0.72 * downPixel.green + 0.07 * downPixel.blue; gradient.Y = pixelGrayVal - downPixelGrayVal; } if (x == GetWidth(ImageMatrix) - 1) { //boundary pixel. gradient.X = 0; } else { RGBPixel rightPixel = ImageMatrix[y, x + 1]; double rightPixelGrayVal = 0.21 * rightPixel.red + 0.72 * rightPixel.green + 0.07 * rightPixel.blue; gradient.X = pixelGrayVal - rightPixelGrayVal; } return(gradient); }
/// <summary> /// Open an image and load it into 2D array of colors (size: Height x Width) /// </summary> /// <param name="ImagePath">Image file path</param> /// <returns>2D array of colors</returns> public static RGBPixel[,] OpenImage(string ImagePath) { Bitmap original_bm = new Bitmap(ImagePath); int Height = original_bm.Height; int Width = original_bm.Width; RGBPixel[,] Buffer = new RGBPixel[Height, Width]; unsafe { BitmapData bmd = original_bm.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, original_bm.PixelFormat); int x, y; int nWidth = 0; bool Format32 = false; bool Format24 = false; bool Format8 = false; if (original_bm.PixelFormat == PixelFormat.Format24bppRgb) { Format24 = true; nWidth = Width * 3; } else if (original_bm.PixelFormat == PixelFormat.Format32bppArgb || original_bm.PixelFormat == PixelFormat.Format32bppRgb || original_bm.PixelFormat == PixelFormat.Format32bppPArgb) { Format32 = true; nWidth = Width * 4; } else if (original_bm.PixelFormat == PixelFormat.Format8bppIndexed) { Format8 = true; nWidth = Width; } int nOffset = bmd.Stride - nWidth; byte *p = (byte *)bmd.Scan0; for (y = 0; y < Height; y++) { for (x = 0; x < Width; x++) { if (Format8) { Buffer[y, x].red = Buffer[y, x].green = Buffer[y, x].blue = p[0]; p++; } else { Buffer[y, x].red = p[0]; Buffer[y, x].green = p[1]; Buffer[y, x].blue = p[2]; if (Format24) { p += 3; } else if (Format32) { p += 4; } } } p += nOffset; } original_bm.UnlockBits(bmd); } return(Buffer); }
/// <summary> /// Apply Gaussian smoothing filter to enhance the edge detection /// </summary> /// <param name="ImageMatrix">Colored image matrix</param> /// <param name="filterSize">Gaussian mask size</param> /// <param name="sigma">Gaussian sigma</param> /// <returns>smoothed color image</returns> public static RGBPixel[,] GaussianFilter1D(RGBPixel[,] ImageMatrix, int filterSize, double sigma) { int Height = GetHeight(ImageMatrix); int Width = GetWidth(ImageMatrix); RGBPixelD[,] VerFiltered = new RGBPixelD[Height, Width]; RGBPixel[,] Filtered = new RGBPixel[Height, Width]; // Create Filter in Spatial Domain: //================================= //make the filter ODD size if (filterSize % 2 == 0) { filterSize++; } double[] Filter = new double[filterSize]; //Compute Filter in Spatial Domain : //================================== double Sum1 = 0; int HalfSize = filterSize / 2; for (int y = -HalfSize; y <= HalfSize; y++) { //Filter[y+HalfSize] = (1.0 / (Math.Sqrt(2 * 22.0/7.0) * Segma)) * Math.Exp(-(double)(y*y) / (double)(2 * Segma * Segma)) ; Filter[y + HalfSize] = Math.Exp(-(double)(y * y) / (double)(2 * sigma * sigma)); Sum1 += Filter[y + HalfSize]; } for (int y = -HalfSize; y <= HalfSize; y++) { Filter[y + HalfSize] /= Sum1; } //Filter Original Image Vertically: //================================= int ii, jj; RGBPixelD Sum; RGBPixel Item1; RGBPixelD Item2; for (int j = 0; j < Width; j++) { for (int i = 0; i < Height; i++) { Sum.red = 0; Sum.green = 0; Sum.blue = 0; for (int y = -HalfSize; y <= HalfSize; y++) { ii = i + y; if (ii >= 0 && ii < Height) { Item1 = ImageMatrix[ii, j]; Sum.red += Filter[y + HalfSize] * Item1.red; Sum.green += Filter[y + HalfSize] * Item1.green; Sum.blue += Filter[y + HalfSize] * Item1.blue; } } VerFiltered[i, j] = Sum; } } //Filter Resulting Image Horizontally: //=================================== for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { Sum.red = 0; Sum.green = 0; Sum.blue = 0; for (int x = -HalfSize; x <= HalfSize; x++) { jj = j + x; if (jj >= 0 && jj < Width) { Item2 = VerFiltered[i, jj]; Sum.red += Filter[x + HalfSize] * Item2.red; Sum.green += Filter[x + HalfSize] * Item2.green; Sum.blue += Filter[x + HalfSize] * Item2.blue; } } Filtered[i, j].red = (byte)Sum.red; Filtered[i, j].green = (byte)Sum.green; Filtered[i, j].blue = (byte)Sum.blue; } } return(Filtered); }