I'm trying to separate a greylevel image based on pixel-value: suppose pixels from 0 to 60 in one bin, 60-120 in another, 120-180 ... and so on til 255. The ranges are roughly equispaced in this case. However by using K-means clustering will it be possible to get more realistic measures of what my pixel value ranges should be? Trying to obtain similar pixels together and not waste bins where there is lower concentration of pixels present.
EDITS (to include obtained results):
k-means with no of cluster = 5
Image segmentation is the classification of an image into different groups. Many researches have been done in the area of image segmentation using clustering. There are different methods and one of the most popular methods is k-means clustering algorithm.
It is used to identify different classes or clusters in the given data based on how similar the data is. Data points in the same group are more similar to other data points in that same group than those in other groups. K-means clustering is one of the most commonly used clustering algorithms.
The K-means clustering algorithm is used to find groups which have not been explicitly labeled in the data. This can be used to confirm business assumptions about what types of groups exist or to identify unknown groups in complex data sets.
Advantages of k-meansGuarantees convergence. Can warm-start the positions of centroids. Easily adapts to new examples. Generalizes to clusters of different shapes and sizes, such as elliptical clusters.
Of course K-Means can be used for color quantization. It's very handy for that.
Let's see an example in Mathematica:
We start with a greyscale (150x150) image:
Let's see how many grey levels are there when representing the image in 8 bits:
ac = ImageData[ImageTake[i, All, All], "Byte"];
First@Dimensions@Tally@Flatten@ac
-> 234
Ok. Let's reduce those 234 levels. Our first try will be to let the algorithm alone to determine how many clusters are there with the default configuration:
ic = ClusteringComponents[Image@ac];
First@Dimensions@Tally@Flatten@ic
-> 3
It selects 3 clusters, and the corresponding image is:
Now, if that is ok, or you need more clusters, is up to you.
Let's suppose you decide that a more fine-grained color separation is needed. Let's ask for 6 clusters instead of 3:
ic2 = ClusteringComponents[Image@ac, 6];
Image@ic2 // ImageAdjust
Result:
and here are the pixel ranges used in each bin:
Table[{Min@#, Max@#} &@(Take[orig, {#[[1]]}, {#[[2]]}] & /@
Position[clus, n]), {n, 1, 6}]
-> {{0, 11}, {12, 30}, {31, 52}, {53, 85}, {86, 134}, {135, 241}}
and the number of pixels in each bin:
Table[Count[Flatten@clus, i], {i, 6}]
-> {8906, 4400, 4261, 2850, 1363, 720}
So, the answer is YES, and it is straightforward.
Edit
Perhaps this will help you understand what you are doing wrong in your new example.
If I clusterize your color image, and use the cluster number to represent brightness, I get:
That's because the clusters are not being numbered in an ascending brightness order.
But if I calculate the mean brightness value for each cluster, and use it to represent the cluster value, I get:
In my previous example, that was not needed, but that was just luck :D (i.e. clusters were found in ascending brightness order)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With