public double GetEuclClr(KMCPoint <int> Point1, KMCPoint <int> Point2) { // Compute the Euclidian distance between two colors in the 3D-space return(Math.Sqrt(Math.Pow(Math.Abs(Point1.Clr.R - Point2.Clr.R), 2) + Math.Pow(Math.Abs(Point1.Clr.G - Point2.Clr.G), 2) + Math.Pow(Math.Abs(Point1.Clr.B - Point2.Clr.B), 2))); }
private bool IsValidDistance(List <KMCPoint <int> > Points, KMCPoint <int> Target, Int32 Distance) { Int32 Index = -1; bool Exists = false; // Iterate through the array of super-pixels until we've found the super-pixel which // distance to the target super-pixel is less than or equals to the specified boundary while (++Index < Points.Count() && !Exists) { // For each super-pixel from the array we compute the value of distance and // perform a check if the following value is less than or equals to // the value of specific boundary parameter. Exists = ((Math.Abs(Target.X - Points.ElementAt(Index).X) <= Distance) || (Math.Abs(Target.Y - Points.ElementAt(Index).Y) <= Distance)) ? true : false; } return(Exists); }
private bool IsValidColor(List <KMCPoint <int> > Points, KMCPoint <int> Target, Int32 Offset) { Int32 Index = -1; bool Exists = false; // Iterate through the array of super-pixels until we've found the super-pixel which // color offset to the target super-pixel is less than or equals to the specified boundary while (++Index < Points.Count() && !Exists) { // For each super-pixel from the array we compute the value of color offset and // perform a check if the following value is less than or equals to // the value of specific boundary parameter. Exists = (Math.Sqrt(Math.Pow(Math.Abs(Points[Index].Clr.R - Target.Clr.R), 2) + Math.Pow(Math.Abs(Points[Index].Clr.G - Target.Clr.G), 2) + Math.Pow(Math.Abs(Points[Index].Clr.B - Target.Clr.B), 2))) <= Offset ? true : false; } return(Exists); }
public void Init(Bitmap Filename, Int32 Distance, Int32 Offset) { // Declare a bitmap object to load and use the original image to be segmented LockedBitmap FrameBuffer = new LockedBitmap(Filename); // Initialize the array of super-pixels by creating List<KMCPoint<int>> class object List <KMCPoint <int> > Centroids = new List <KMCPoint <int> >(); // Generate an initial array of super-pixels of the original source image // stored in the FrameBuffer bitmap object this.Generate(ref Centroids, FrameBuffer, Distance, Offset); // Compute the value of the centeral super-pixel coordinates and assign it // to the Mean local variable KMCPoint <int> Mean = this.GetMean(FrameBuffer, Centroids); // Append an initial cluster being initialized to the array of clusters m_Clusters.Add(new KMCFrame(FrameBuffer, Centroids, Mean)); }
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 void Add(LockedBitmap FrameImage, List <KMCPoint <int> > Centroids, KMCPoint <int> Center) { m_Clusters.Add(new KMCFrame(FrameImage, Centroids, Center)); }
// KMCFrame Constructor public KMCFrame(LockedBitmap Frame, List <KMCPoint <Int32> > Centroids, KMCPoint <Int32> Center) { this.Frame = Frame; this.m_Centroids = Centroids; this.Center = Center; }
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); }
public double GetEuclD(KMCPoint <int> Point1, KMCPoint <int> Point2) { // Compute the Euclidian distance between two pixel in the 2D-space return(Math.Sqrt(Math.Pow(Point1.X - Point2.X, 2) + Math.Pow(Point1.Y - Point2.Y, 2))); }