/// <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(0, 0); 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); }
public static RGBPixel[,] fill(List<Point> selected_points, RGBPixel[,] ImageMatrix) { Boundary bondry = GET_Boundary(selected_points); // Boundary of the main selection selected_image = Helper.COPY_Segment(ImageMatrix,bondry); // get croped image block_border(selected_points,bondry); // assign the selected point as blocks Flood_Fill(ImageOperations.GetWidth(selected_image) - 1, ImageOperations.GetHeight(selected_image) - 1); return selected_image; }
public static RGBPixel[,] CopyImage(RGBPixel[,] ImageMatrix, Boundary border) { int Width = border.MAX_X - border.MIN_X; int Height = border.MAX_Y - border.MIN_Y; RGBPixel[,] SelectedImage = new RGBPixel[Height + 1, Width + 1]; for (int i = 0; i <= Height; i++) { for (int j = 0; j <= Width; j++) { SelectedImage[i, j] = ImageMatrix[border.MIN_Y + i, border.MIN_X + j]; } } return(SelectedImage); }
public static RGBPixel[ , ] COPY(RGBPixel [ , ] ImageMatrix) { int Width = ImageOperations.GetWidth(ImageMatrix); int Height = ImageOperations.GetHeight(ImageMatrix); RGBPixel[,] selected_image = new RGBPixel[Height, Width]; for (int r = 0; r < Height; r++) { for (int c = 0; c < Width; c++) { selected_image [r, c] = ImageMatrix [r, c]; } } return(selected_image); }
public static RGBPixel[ , ] COPY_Segment(RGBPixel [ , ] ImageMatrix, Boundary bondry) { // copy a segment from image matrix into anew one int Width = bondry.MAX_X - bondry.MIN_X; // new segment widtrh int Height = bondry.MAX_Y - bondry.MIN_Y; // new segment height RGBPixel[,] selected_image = new RGBPixel[Height + 1, Width + 1]; for (int r = 0; r <= Height; r++) { for (int c = 0; c <= Width; c++) { selected_image [r, c] = ImageMatrix [bondry.MIN_Y + r, bondry.MIN_X + c]; } } return(selected_image); }
public CropedImage(RGBPixel[,] cropedImage) { InitializeComponent(); ImageOperations.DisplayImage(cropedImage, pictureBox1); }
/// <summary> /// generate the shortest path from source node to all other nodes /// </summary> /// <param name="Graph"></param> /// <param name="Source"></param> /// <param name="Dest"></param> /// <returns></returns> public static List<Point> GenerateShortestPath(int Source, int Dest, RGBPixel[,] ImageMatrix) { // return sortest path btween src & all other nodes List<int> Previous_list = Dijkstra(Source, Dest, ImageMatrix); // Backtracking shortest path to (Dest)node from previous list return Backtracking(Previous_list, Dest, ImageOperations.GetWidth(ImageMatrix)); }
/// <summary> /// Get the width of the image /// </summary> /// <param name="ImageMatrix">2D array that contains the image</param> /// <returns>Image Width</returns> public static int GetWidth(RGBPixel[,] ImageMatrix) { return ImageMatrix.GetLength(1); }
/// <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(0, 0); 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]; // Load the image to the 2D-array 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); } ////////////////////////////////////////////// //Additional part to initialize pixels as not visited yet. ////////////////////////////////////////////// for (int y = 0; y < Height; y++) for (int x = 0; x < Width; x++) Buffer[y, x].block = false; 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; } for (int y = 0; y < Height; y++) for (int x = 0; x < Width; x++) Filtered[y, x].block = false; return Filtered; }
/// <summary> /// Display the given image on the given PictureBox object /// </summary> /// <param name="ImageMatrix">2D array that contains the image</param> /// <param name="PicBox">PictureBox object to display the image on it</param> public static void DisplayImage(RGBPixel[,] ImageMatrix, PictureBox PicBox) { // Create Image: //============== int Height = ImageMatrix.GetLength(0); int Width = ImageMatrix.GetLength(1); Bitmap ImageBMP = new Bitmap(Width, Height, PixelFormat.Format24bppRgb); unsafe { BitmapData bmd = ImageBMP.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, ImageBMP.PixelFormat); int nWidth = 0; nWidth = Width * 3; int nOffset = bmd.Stride - nWidth; byte* p = (byte*)bmd.Scan0; for (int i = 0; i < Height; i++) { for (int j = 0; j < Width; j++) { p[0] = ImageMatrix[i, j].red; p[1] = ImageMatrix[i, j].green; p[2] = ImageMatrix[i, j].blue; p += 3; } p += nOffset; } ImageBMP.UnlockBits(bmd); } PicBox.Image = ImageBMP; }
/// <summary> /// Calculate edge energy between /// 1. the given pixel and its right one (X) /// 2. the given pixel and its bottom one (Y) /// </summary> /// <param name="x">pixel x-coordinate</param> /// <param name="y">pixel y-coordinate</param> /// <param name="ImageMatrix">colored image matrix</param> /// <returns>edge energy with the right pixel (X) and with the bottom pixel (Y)</returns> public static Vector2D CalculatePixelEnergies(int x, int y, RGBPixel[,] ImageMatrix) { if (ImageMatrix == null) throw new Exception("image is not set!"); Vector2D gradient = CalculateGradientAtPixel(x, y, ImageMatrix); double gradientMagnitude = Math.Sqrt(gradient.X * gradient.X + gradient.Y * gradient.Y); double edgeAngle = Math.Atan2(gradient.Y, gradient.X); double rotatedEdgeAngle = edgeAngle + Math.PI / 2.0; Vector2D energy = new Vector2D( Math.Abs(gradientMagnitude * Math.Cos(rotatedEdgeAngle)), Math.Abs(gradientMagnitude * Math.Sin(rotatedEdgeAngle))); return energy; }
/// <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); }
public static List<int> Dijkstra(int Source, int dest, RGBPixel[,] ImageMatrix) { const double oo = 10000000000000000000; // infity value //Distance : the minimum cost between the source node and all the others nodes //initialized with infinty value int Width = ImageOperations.GetWidth(ImageMatrix); int Height = ImageOperations.GetHeight(ImageMatrix); int nodes_number = Width * Height; List<double> Distance = new List<double>(); Distance = Enumerable.Repeat(oo, nodes_number).ToList(); //Previous : saves the previous node that lead to the shortest path from the src node to current node List<int> Previous = new List<int>(); Previous = Enumerable.Repeat(-1, nodes_number).ToList(); // PeriorityQueue : always return the shortest bath btween src node and specific node PeriorityQueue MinimumDistances = new PeriorityQueue(); MinimumDistances.Push(new Edge(-1, Source, 0)); while (!MinimumDistances.IsEmpty()) { // get the shortest path so far Edge CurrentEdge = MinimumDistances.Top(); MinimumDistances.Pop(); // check if this SP is vaild (i didn't vist this node with a less cost) if (CurrentEdge.Weight >= Distance[CurrentEdge.To]) continue; // save the previous Previous[CurrentEdge.To] = CurrentEdge.From; Distance[CurrentEdge.To] = CurrentEdge.Weight; if (CurrentEdge.To == dest) break; // Relaxing List<Edge> neibours = GraphOperations.Get_neighbours(CurrentEdge.To, ImageMatrix); for (int i = 0; i < neibours.Count; i++) { Edge HeldEdge = neibours[i]; // if the relaxed path cost of a neighbour node is less than it's previous one if (Distance[HeldEdge.To] > Distance[HeldEdge.From] + HeldEdge.Weight) { // set the relaxed cost to Distance && pash it to the PQ HeldEdge.Weight = Distance[HeldEdge.From] + HeldEdge.Weight; MinimumDistances.Push(HeldEdge); } } } return Previous; // re turn th shortest paths from src to all nodes }
/// <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> /// Get the height of the image /// </summary> /// <param name="ImageMatrix">2D array that contains the image</param> /// <returns>Image Height</returns> public static int GetHeight(RGBPixel[,] ImageMatrix) { return ImageMatrix.GetLength(0); }