public KMCPoint <int> GetMean(LockedBitmap FrameBuffer, List <KMCPoint <int> > Centroids) { // Declaring two variables to assign the value of the "mean" of // the sets of coordinates (X;Y) of each super-pixel double Mean_X = 0, Mean_Y = 0; // Iterating through the array of super-pixels and for each // super-pixel retrieve its X and Y coordinates and divide it // by the overall amount of super-pixels. After that, sum up // each value with the values of Mean_X and Mean_Y variables for (Int32 Index = 0; Index < Centroids.Count(); Index++) { Mean_X += Centroids[Index].X / (double)Centroids.Count(); Mean_Y += Centroids[Index].Y / (double)Centroids.Count(); } // Convert the values of Mean_X and Mean_Y to Int32 datatype Int32 X = Convert.ToInt32(Mean_X); Int32 Y = Convert.ToInt32(Mean_Y); FrameBuffer.LockBits(); Color Clr = FrameBuffer.GetPixel(X, Y); FrameBuffer.UnlockBits(); // Constructing KMCPoint<int> object and return its value return(new KMCPoint <int>(X, Y, Clr)); }
public void Generate(ref List <KMCPoint <int> > Centroids, LockedBitmap ImageFrame, Int32 Distance, Int32 Offset) { // Compute the number of iterations performed by the main loop equal to image W * H // The following value is the maximum possible number of random super-pixel being generated Int32 Size = ImageFrame.Width * ImageFrame.Height; ImageFrame.LockBits(); // Performing Size - iterations of the following loop to generate a specific amount of super-pixels for (Int32 IterCount = 0; IterCount < Size; IterCount++) { // Obtain a random value of X - coordinate of the current super-pixel Int32 Rand_X = rand.Next(0, ImageFrame.Width); // Obtain a random value of Y - coordinate of the current super-pixel Int32 Rand_Y = rand.Next(0, ImageFrame.Height); // Create and instantinate a point object by using the values of // Rand_X, Rand_Y and Colorref parameters. The value of colorref is // retrieved by using the GetPixel method for the current bitmap object KMCPoint <int> RandPoint = new KMCPoint <int>(Rand_X, Rand_Y, ImageFrame.GetPixel(Rand_X, Rand_Y)); // Performing a validity check if none of those super-pixel previously // selected don't exceed the distance and color offset boundary to the // currently generated super-pixel with coordinates Rand_X and Rand_Y and // specific color stored as a parameter value of Clr variable if (!this.IsValidColor(Centroids, RandPoint, Offset) && !this.IsValidDistance(Centroids, RandPoint, Distance)) { // If not, check if the super-pixel with the following coordinates and color // already exists in the array of centroid super-pixels being generated. if (!Centroids.Contains(RandPoint)) { // If not, append the object RandPoint to the array of super-pixel objects Centroids.Add(RandPoint); } } } ImageFrame.UnlockBits(); }
public Bitmap Compute(Bitmap InputFile) { // Initialize the code execution timer var watch = System.Diagnostics.Stopwatch.StartNew(); // Initialize the directory info reference object DirectoryInfo dir_info = new DirectoryInfo("Clusters"); // Check if the directory with name "Clusters" is created. // If not, create the directory with name "Clusters" if (dir_info.Exists == false) { dir_info.Create(); } // Initialize the array of clusters by generating an initial cluster // containing the original source image associated with the array of super-pixels m_Clusters.Init((Bitmap)InputFile.Clone(), m_Distance, m_OffsetClr); // Initialize the bitmap object used to store the resulting segmented image LockedBitmap ResultBitmap = new LockedBitmap(m_Clusters[0].Frame.Width, m_Clusters[0].Frame.Height); Int32 FrameIndex = 0; // Iterate throught the array of clusters until we've process all clusters being generated for (Int32 Index = 0; Index < m_Clusters.Count(); Index++) { // For each particular cluster from the array, obtain the values of bitmap object and // the List<KMCPoint<int>> object which is the array of centroid super-pixels List <KMCPoint <int> > Centroids = m_Clusters[Index].Centroids.ToList(); LockedBitmap FrameBuffer = new LockedBitmap(m_Clusters[Index].Frame.m_Bitmap); // Save the image containg the segmented area associated with the current cluster to the // specific file, which name has the following format, for example "D:\Clusters\Cluster_N.jpg" FrameBuffer.Save("Clusters\\Cluster_" + FrameIndex + ".jpg"); FrameBuffer.LockBits(); // Iterating through the array of centroid super pixels and for each super-pixels // perform a linear search to find all those pixel in the current image which distance // does not exceed the value of specific boundary parameter. for (Int32 Cnt = 0; Cnt < Centroids.Count(); Cnt++) { // Obtain the value of Width and Height of the image for the current cluster Int32 Width = FrameBuffer.Width; Int32 Height = FrameBuffer.Height; // Create a bitmap object to store an image for the newly built cluster LockedBitmap TargetFrame = new LockedBitmap(FrameBuffer.Width, FrameBuffer.Height); TargetFrame.LockBits(); // Iterate through each element of the matrix of pixels for the current image for (Int32 Row = 0; Row < FrameBuffer.Width; Row++) { for (Int32 Col = 0; Col < Height; Col++) { // For each pixel in this matrix, compute the value of color offset of the current centroid super-pixel double OffsetClr = GetEuclClr(new KMCPoint <int>(Row, Col, FrameBuffer.GetPixel(Row, Col)), new KMCPoint <int>(Centroids[Cnt].X, Centroids[Cnt].Y, Centroids[Cnt].Clr)); //Perform a check if the color offset value does not exceed the value of boundary parameter if (OffsetClr <= 50) { // Copy the current pixel to the target image for the newly created cluster TargetFrame.SetPixel(Row, Col, Centroids[Cnt].Clr); } // Otherwise, set the color of the current pixel to "white" (R;G;B) => (255;255;255) // in the target bitmap for the newly built cluster else { TargetFrame.SetPixel(Row, Col, Color.FromArgb(255, 255, 255)); } } } TargetFrame.UnlockBits(); // Create an array of centroid super-pixels and append // it the value of current centroid super-pixel retrieved List <KMCPoint <int> > TargetCnts = new List <KMCPoint <int> >(); TargetCnts.Add(Centroids[0]); // Compute the "mean" value for the newly created cluster KMCPoint <int> Mean = m_Clusters.GetMean(TargetFrame, TargetCnts); // Perform a check if the "mean" point coordinates of the newly created cluster are // not equal to the coordinates of the current centroid super-pixel (e.g. the centroid // super-pixel has been moved). If so, append a newly built cluster to the array of clusters if (Mean.X != m_Clusters[Index].Center.X && Mean.Y != m_Clusters[Index].Center.Y) { m_Clusters.Add(TargetFrame, TargetCnts, Mean); } FrameIndex++; } FrameBuffer.UnlockBits(); } ResultBitmap.LockBits(); // Iterate through the array of clusters previously obtained for (Int32 Index = 0; Index < m_Clusters.Count(); Index++) { // For each cluster retrieve a specific image containing the segmented area LockedBitmap FrameOut = new LockedBitmap(m_Clusters[Index].Frame.m_Bitmap); FrameOut.LockBits(); FrameOut.Save("temp_" + Index + ".jpg"); // Obtain the dimensions of that image int Width = FrameOut.Width, Height = FrameOut.Height; // Iterate through the matrix of pixels for the current image and for each // pixel perform a check if its color is not equal to "white" (R;G;B) => (255;255;255). // If not, copy the pixel data to the target matrix of pixels for the resulting segmented image for (Int32 Row = 0; Row < Width; Row++) { for (Int32 Col = 0; Col < Height; Col++) { if (FrameOut.GetPixel(Row, Col) != Color.FromArgb(255, 255, 255)) { ResultBitmap.SetPixel(Row, Col, FrameOut.GetPixel(Row, Col)); } } } FrameOut.UnlockBits(); } ResultBitmap.UnlockBits(); // Save the segmented image to file with name which is the value of OutputFile variable //ResultBitmap.Save(OutputFile); watch.Stop(); // Stop the execution timer // Obtain the value of executing time in milliseconds var elapsedMs = watch.ElapsedMilliseconds; // Create timespan from the elapsed milliseconds value TimeSpan ts = TimeSpan.FromMilliseconds(elapsedMs); // Print the message "Done" and the formatted execution time Console.WriteLine("***Done***\n" + ts.ToString(@"hh\:mm\:ss")); return(ResultBitmap.m_Bitmap); }