/// <summary> /// Calculates the centroids of the clusters /// </summary> public void CalculateClusterCentroids() { //Console.WriteLine("Cluster Centroid calculation:"); for (int j = 0; j < this.Clusters.Count; j++) { ClusterCentroid c = this.Clusters[j]; double l = 0.0; c.PixelCount = 1; c.RSum = 0; c.GSum = 0; c.BSum = 0; c.MembershipSum = 0; for (int i = 0; i < this.Points.Count; i++) { ClusterPoint p = this.Points[i]; l = Math.Pow(U[i, j], this.Fuzzyness); c.RSum += l * p.PixelColor.R; c.GSum += l * p.PixelColor.G; c.BSum += l * p.PixelColor.B; c.MembershipSum += l; if (U[i, j] == p.ClusterIndex) { c.PixelCount += 1; } } c.PixelColor = Color.FromArgb((byte)(c.RSum / c.MembershipSum), (byte)(c.GSum / c.MembershipSum), (byte)(c.BSum / c.MembershipSum)); } //update the original image Bitmap tempImage = new Bitmap(myImageWidth, myImageHeight, PixelFormat.Format32bppRgb); for (int j = 0; j < this.Points.Count; j++) { for (int i = 0; i < this.Clusters.Count; i++) { ClusterPoint p = this.Points[j]; if (U[j, i] == p.ClusterIndex) { tempImage.SetPixel((int)p.X, (int)p.Y, this.Clusters[i].PixelColor); } } } processedImage = tempImage; }
/// <summary> /// Initialize the algorithm with points and initial clusters /// </summary> /// <param name="points">The list of Points objects</param> /// <param name="clusters">The list of Clusters objects</param> /// <param name="fuzzy">The fuzzyness factor to be used, constant</param> /// <param name="myImage">A working image, so that the GUI working image can be updated</param> /// <param name="numCluster">The number of clusters requested by the user from the GUI</param> public KMeansAlgorithm(List <ClusterPoint> points, List <ClusterCentroid> clusters, float fuzzy, Bitmap myImage, int numCluster) { if (points == null) { throw new ArgumentNullException("points"); } if (clusters == null) { throw new ArgumentNullException("clusters"); } processedImage = (Bitmap)myImage.Clone(); this.Points = points; this.Clusters = clusters; this.myImageHeight = myImage.Height; this.myImageWidth = myImage.Width; this.myImage = new Bitmap(myImageWidth, myImageHeight, PixelFormat.Format32bppRgb); U = new double[this.Points.Count, this.Clusters.Count]; this.Fuzzyness = fuzzy; double diff; // Iterate through all points to create initial U matrix for (int i = 0; i < this.Points.Count; i++) { ClusterPoint p = this.Points[i]; double sum = 0.0; for (int j = 0; j < this.Clusters.Count; j++) { ClusterCentroid c = this.Clusters[j]; diff = Math.Sqrt(Math.Pow(CalculateEuclideanDistance(p, c), 2.0)); U[i, j] = (diff == 0) ? Eps : diff; sum += U[i, j]; } } this.RecalculateClusterMembershipValues(); }
/// <summary> /// Calculates Euclidean Distance distance between a point and a cluster centroid /// </summary> /// <param name="p">Point</param> /// <param name="c">Centroid</param> /// <returns>Calculated distance</returns> private double CalculateEuclideanDistance(ClusterPoint p, ClusterCentroid c) { return(Math.Sqrt(Math.Pow(p.PixelColor.R - c.PixelColor.R, 2.0) + Math.Pow(p.PixelColor.G - c.PixelColor.G, 2.0) + Math.Pow(p.PixelColor.B - c.PixelColor.B, 2.0))); }