Using system;using system.drawing;using system.windows.forms;using system.threading;using System.collections.generic;namespace k_means{public partial class Form1:form {const int picturesize = 640 * 480; const int k = 3; The number of centroid color[] Arraycolor = new Color[picturesize]; Data set int[,] resultarray = new int[picturesize, 2]; Store the result of the cluster allocation for each point and the distance to the centroid int[,] Centarray = new int[k, 4]; Storage centroid int[,] Tmpcentarray = new int[k, 4]; Public Form1 () {InitializeComponent (); Picturebox1.imagelocation = "Test.jpg"; } private void Button1_Click (object sender, EventArgs e) {Bitmap map = new Bitmap (picturebox1.im Age); for (int j = 0; J < map. Height; J + +) {for (int i = 0; i < map. Width; i++) {arraycolor[j * map. Width + i] = map. GetPixel (i, j); } } New Thread (new ThreadStart (Kmeans)). Start (); private void Button1_resize (object sender, EventArgs e) {this. Width = 800; This. Height = 600; } private void Button2_Click (object sender, EventArgs e) {Bitmap map = new Bitmap (picturebox1.im Age); Bitmap newmap = map; Color color = new color (); Color Newcolor = new color (); Byte R, G, B, gray; for (int j = 0; J < map. Height; J + +) {for (int i = 0; i < map. Width; i++) {color = map. GetPixel (i, j); R = Color. R g = Color. G b = Color. B if (r + G + b! = 0) {Gray = (Byte) ((R * 19595 + G * 38469 + b * 7472) >> 16); Newcolor = Color.FromArgb (Gray, Gray, gray); Newmap. SeTpixel (i, J, Newcolor); }}} pictureBox1.Image = Newmap; } private int Getdistance (int[,] A, Color b, int i) {return (int) math.sqrt (Math.pow (a[i, 0]-B. R, 2) + Math.pow (a[i, 1]-B.G, 2) + Math.pow (A[i, 2]-b.b, 2) + Math.pow (A[i, 3]-B.A, 2)); } private void Kmeans () {DateTime dt = DateTime.Now; for (int i = 0; i < K; i++)//initial k random centroid, color value does not look at data set, direct 0-255 {tmpcentarray[i, 0] = centarray[ I, 0] = new Random (Bitconverter.toint32 (GUID.NEWGUID). Tobytearray (), 0)). Next (0, 256); Tmpcentarray[i, 1] = centarray[i, 1] = new Random (Bitconverter.toint32 (Guid.NewGuid (). Tobytearray (), 0)). Next (0, 256); Tmpcentarray[i, 2] = centarray[i, 2] = new Random (Bitconverter.toint32 (Guid.NewGuid (). Tobytearray (), 0)). Next (0, 256); Tmpcentarray[i, 3] = centarray[i, 3] = new Random (Bitconverter.toint32 (GUid. NewGuid (). Tobytearray (), 0)). Next (0, 256); } while (true) {for (int i = 0; i < arraycolor.length; i++)//Traverse data Set each point and cluster allocation {int mindistance = getdistance (Centarray, Arraycolor[i], 0); int count = 0; for (int j = 1; j < K; J + +) {int tmpdistance = getdistance (Centarray, ARRAYC Olor[i], J); if (Mindistance > tmpdistance) {mindistance = tmpdistance; Count = j; }} resultarray[i, 0] = count; Resultarray[i, 1] = mindistance; } for (int j = 0; J < 3; J + +)//calculate new centroid {int r = 0; int g = 0; int b = 0; int a = 0; int m = 0; for (int i = 0; i < arraycolor.length; i++) {if (resultarray[i, 0] = = j) {r + = Arraycolor[i]. R G + = Arraycolor[i]. G B + = Arraycolor[i]. B A + = Arraycolor[i]. A m++; }} if (M! = 0) {centarray[j, 0] = r/m; Centarray[j, 1] = g/m; Centarray[j, 2] = b/m; Centarray[j, 3] = a/m; } this. Invoke (new MethodInvoker () = {This.label1.Text = centarray[j, 0] + "\ r \ n" + centarray[j, 1] + "\ r \ n" + centarray[j, 2] + "\ r \ n" + centarray[j, 3] + "\ r \ n" + (DATETIME.NOW-DT). TotalSeconds; })); } bool Isbreak= true; for (int i = 0; i < K; i++)//detect if the centroid is still changed {for (int j = 0; J < 4, j + +) {if (tmpcentarray[i, j]! = Centarray[i, j]) { Isbreak = false; Break }}} if (Isbreak)//center of mass is not changed, you can exit { Break } else {for (int i = 0; i < K; i++)//Save the calculated centroid of the previous round {for (int j = 0; J < 4; J + +) {Tmpcentarra Y[i, j] = Centarray[i, j]; }}}}} private void Button3_Click (object sender, EventArgs E {Bitmap map = new Bitmap (picturebox1.width, picturebox1.height); for (int j = 0; J < map. Height; J + +) {for (int i = 0; i < map. Width; i++) {if (RESULTARRAY[J * map. Width + I, 0] = = 0) {map. SetPixel (i, J, color.red); } else if (RESULTARRAY[J * map. Width + I, 0] = = 1) {map. SetPixel (i, J, Color.green); } else if (RESULTARRAY[J * map. Width + I, 0] = = 2) {map. SetPixel (i, J, Color.yellow); }}} pictureBox1.Image = map; } }}
Code casually write, no optimization, the two points K-means some details have not been clear, had to first use the general K-means do, the effect is to see below it.
<machine Learning in Action > 42-point K-Means algorithm C # to achieve image segmentation