且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

OpenCV使用k-means来分色图像

更新时间:2023-12-02 21:48:28

我不是OpenCV的专家,因此我将提供与您的问题相关的一般性建议K-means获取向量列表,该列表基本上是一个矩阵:

I am no expert in OpenCV so I will give a general advice that relates to your question K-means takes list of vectors which is essentially a matrix:

[x0, y0, r0, g0, b0]
[x1, y1, r1, g1, b1]
[x2, y2, r2, g2, b2]
.
.
.

您正在给它一张无效的图像。首先必须将图像转换为此k-means矩阵格式。对于源图像的每个像素,在结果矩阵中有一行。另请注意,您应该缩放值,使它们都具有相似的值。如果不这样做,x和y坐标的重力通常会高于颜色,导致结果不令人满意。 C ++伪代码:

You are giving it an image which is not going to work. You first have to convert the image to this k-means matrix format. For each pixel of the source image you have one row in the resulting matrix. Also note that you should scale the values so that they all have similar values. If you don't do that, x and y coordinates will usually have much higher "gravity" than the color which leads to unsatisfactory results. C++ pseudocode:

int pixel_index = 0;
for (int y = 0; y < image height; y++)  {
  for (int x = 0; x < image width; x++)  {
     matrix[pixel_index][0] = (float)x / image width;
     matrix[pixel_index][1] = (float)y / image height;
     matrix[pixel_index][2] = (float)pixel(x, y).r / 255.0f;
     matrix[pixel_index][3] = (float)pixel(x, y).g / 255.0f;
     matrix[pixel_index][4] = (float)pixel(x, y).b / 255.0f;
  }
}
// Pass the matrix to kmeans...

因此,您将获得每个像素的标签,这些标签对应于已分配给它的群集。然后,您需要确定聚类的颜色 - 这可以从采用中心像素颜色值到计算聚类的平均/中值颜色。确定颜色后,只需移动图像并将像素设置为其簇颜色:

As a result, you get labels of each individual pixel which corresponds to the cluster it has been assigned to. You then need to determine the color of the clusters - this can vary from taking the center pixel color value to computing an average/median color of the cluster. After you determine the color, just walk the image and set pixels to their cluster colors:

for (int y = 0; y < image height; y++)  {
  for (int x = 0; x < image width; x++)  {
     int index = y * image width + x;  // This corresponds to pixel_index above
     int cluster_index = labels[index]; // 0 to 7 in your case
     Color color = colors[cluster_index];  // Colors is an array of 8 colors of the clusters
     image.setpixel(x, y, color)
  }
}

如果您更喜欢使用HSV而不是RGB,只需使用HSV值而不是RGB值。

If you prefer to use HSV instead of RGB, just use HSV values instead of RGB ones.

OpenCV可能具有完全执行上述转换的功能,但我无法使用Google快速找到它们。

It is possible that OpenCV has functions that perform exactly the conversion I described above but I was unable to quick find them using Google.