Hi, I am trying to implement the K Means Clustering Algorithm for Image Segmentation. The logic behind K Means is :
1. Place K points into the space represented by the objects that are being clustered. These points represent initial group centroids.
2. Assign each object to the group that has the closest centroid.
3. When all objects have been assigned, recalculate the positions of the K centroids.
4. Repeat Steps 2 and 3 until the centroids no longer move. This produces a separation of the objects into groups from which the metric to be minimized can be calculated.
I have written the following code so far :
private void button2_Click(object sender, EventArgs e)
{
int k = 17, a, t, b, addi, sum, cnt = 0,flag=0;
int[] means = new int[k];
List<int>[] buckets = new List<int>[17];
List<Point>[] points = new List<Point>[17];
Bitmap srcimg = (Bitmap)pictureBox1.Image.Clone();
Bitmap dstimg = new Bitmap(pictureBox1.Width, pictureBox1.Height);
AForge.Imaging.Filters.Grayscale g = new Grayscale(0.299, 0.587, 0.114);
srcimg = g.Apply(srcimg);
textBox1.Text = srcimg.PixelFormat.ToString();
BitmapData src = srcimg.LockBits(new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height), ImageLockMode.ReadWrite, srcimg.PixelFormat);
unsafe
{
byte* ptr = (byte*)(void*)src.Scan0;
int[] centroid = { 0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240 };
int[] centroid_old = new int[17];
for (int i = 0; i < dstimg.Width; i++)
{
for (int j = 0; j < dstimg.Height; j++)
{
dstimg.SetPixel(i, j, Color.White);
}
}
start_here:
centroid_old = centroid;
++cnt;
addi = 0;
for (int i = 0; i < k; i++)
{
buckets[i] = new List<int>();
points[i] = new List<Point>();
}
for (int i = 0; i < pictureBox1.Height; i++)
{
for (int j = 0; j < pictureBox1.Width; j++)
{
t = 255;
a = (int)ptr[i * pictureBox1.Width + j];
if (a != 255)
{
for (int l = 0; l < 17; l++)
{
b = Math.Abs(a - centroid[l]);
if (b < t)
{
t = b;
addi = l;
}
}
buckets[addi].Add(a);
points[addi].Add(new Point(i, j));
}
}
}
for (int i = 0; i < k; i++)
{
if (buckets[i].Count != 0)
{
sum = 0;
for (int j = 0; j < buckets[i].Count; j++)
{
sum += buckets[i].ElementAt(j);
}
centroid[i] = (sum / buckets[i].Count);
if (centroid[i] != centroid_old[i])
{
flag = 1;
}
}
}
if (flag == 1)
{
for (int i = 0; i < k; i++)
{
buckets[i].Clear();
points[i].Clear();
}
goto start_here;
}
int cou;
for (int i = 0; i < 17; i++)
{
cou = 0;
while (cou < points[i].Count)
{
Point p = points[i].ElementAt(cou);
if (p.X < pictureBox1.Width && p.Y < pictureBox1.Height)
{
if (dstimg.GetPixel(p.X, p.Y).R == 255 && dstimg.GetPixel(p.X, p.Y).G == 255 && dstimg.GetPixel(p.X, p.Y).B == 255)
dstimg.SetPixel(p.X, p.Y, Color.Red);
}
++cou;
}
}
for (int i = 0; i < 17; i++)
{
textBox2.Text += centroid[i].ToString() + "--";
}
}
srcimg.UnlockBits(src);
System.Drawing.Image img = (System.Drawing.Image)dstimg;
//img.RotateFlip(RotateFlipType.Rotate90FlipX);
pictureBox2.Image = img;
pictureBox2.Visible = true;
textBox1.Text += pictureBox2.Width + "--" + pictureBox2.Height + "--" + pictureBox1.Width + "--" + pictureBox1.Height;
}
As of now, what I have done is for each of the points in lists called points, I am assigning these points to red color. Just to test.
But I face a few problems :
1. If I do not remove the comments for the image flip line, the image is flipped by 270 degrees(i dont know how).
2. If I remove the comments, I get the image without flip, but the image gets cut at certain places ie loss of data.
3. Once the centroids are recomputed, I do not know what to do with them.
Anyone who can help me out? It would be really helpful