K-means可以用来帮助基于像素值的图像分离吗?

时间:2011-03-24 01:43:10

标签: algorithm image image-processing opencv k-means

我正在尝试根据像素值分离greylevel图像:假设一个bin中0到60的像素,另一个bin中的60-120,120-180 ......依此类推255.范围粗略在这种情况下是等间隔的。  但是,通过使用K-means聚类,可以更准确地衡量我的像素值范围应该是多少?试图获得相似的像素,而不是浪费在存在较低像素浓度的区域。

编辑(包括获得的结果): enter image description here enter image description here

k-means,没有cluster = 5

2 个答案:

答案 0 :(得分:10)

当然K-Means可用于颜色量化。它非常方便。

让我们看一下Mathematica中的示例:

我们从灰度(150x150)图像开始:

enter image description here

让我们看看用8位表示图像时有多少灰度级:

ac = ImageData[ImageTake[i, All, All], "Byte"];
First@Dimensions@Tally@Flatten@ac
-> 234

确定。让我们减少234个等级。我们的第一个尝试是让算法单独确定默认配置中有多少个集群:

ic = ClusteringComponents[Image@ac];
First@Dimensions@Tally@Flatten@ic 
-> 3

选择3个聚类,相应的图像为:

enter image description here

现在,如果可以,或者您需要更多群集,那么由您决定。

假设您认为需要更精细的颜色分离。我们要求6个集群而不是3个集群:

ic2 = ClusteringComponents[Image@ac, 6];
Image@ic2 // ImageAdjust  

结果:

enter image description here

以下是每个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}}

和每个bin中的像素数:

Table[Count[Flatten@clus, i], {i, 6}]
-> {8906, 4400, 4261, 2850, 1363, 720}

所以,答案是肯定的,而且很简单。

修改

也许这会帮助您了解新示例中的错误。

如果我将您的彩色图像聚类,并使用簇编号来表示亮度,我会得到:

enter image description here

这是因为群集没有以递增的亮度顺序编号。

但是,如果我计算每个群集的平均亮度值,并用它来表示群集值,我得到:

enter image description here

在我之前的例子中,这不是必需的,但那只是运气:D(即群集按照亮度升序排列)

答案 1 :(得分:2)

k-means可以应用于您的问题。如果是我,我会首先尝试从决策树借来的基本方法(虽然“更简单”取决于你的精确聚类算法!)

假设存在一个bin,开始将像素强度填充到bin中。当bin“足够”时,计算bin(或节点)的平均值和标准差。如果标准偏差大于某个阈值,则将节点分成两半。继续此过程,直到完成所有强度,您将获得更有效的直方图。

当然,可以通过其他细节改进此方法:

  1. 你可以考虑使用峰度作为分裂标准。
  2. 可能会使用偏斜来确定分割发生的位置
  3. 您可能会一直跨越决策树并借用Jini指数来指导分裂(某些分裂技术依赖于更多“异国情调”统计数据,如t检验。)
  4. 最后,您可以执行最终合并传递以折叠任何稀疏填充的节点。
  5. 当然,如果您已经应用了上述所有“改进”,那么您基本上实现了k-means聚类算法的一种变体; - )

    注意:我不同意上面的评论 - 您描述的问题似乎与直方图均衡无关。