在深入探讨我的问题之前,我希望您知道我已阅读此论坛上的其他帖子,但没有人关注我的问题。 特别是,帖子here回答了“如何做到这一点?”的问题。与k-means,虽然我已经知道我必须使用它,我想知道为什么我的实现不起作用。OpenCV:无法使用k-means获得图像分割
我想使用k-means算法根据输入图像的颜色将输入图像的像素分成多个簇。然后,在完成这样的任务之后,我希望每个像素都具有它被分配给的集群中心的颜色。 为参考OpenCV的例子,在网络上检索到的其他的东西,我设计了下面的代码:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat src = imread(argv[1], 1);
// reshape matrix
Mat resized(src.rows*src.cols, 3, CV_8U);
int row_counter = 0;
for(int i = 0; i<src.rows; i++)
{
for(int j = 0; j<src.cols; j++)
{
Vec3b channels = src.at<Vec3b>(i,j);
resized.at<char>(row_counter,0) = channels(0);
resized.at<char>(row_counter,1) = channels(1);
resized.at<char>(row_counter,2) = channels(2);
row_counter++;
}
}
//cout << src << endl;
// change data type
resized.convertTo(resized, CV_32F);
// determine termination criteria and number of clusters
TermCriteria criteria(TermCriteria::COUNT + TermCriteria::EPS, 10, 1.0);
int K = 8;
// apply k-means
Mat labels, centers;
double compactness = kmeans(resized, K, labels, criteria, 10, KMEANS_RANDOM_CENTERS, centers);
// change data type in centers
centers.convertTo(centers, CV_8U);
// create output matrix
Mat result = Mat::zeros(src.rows, src.cols, CV_8UC3);
row_counter = 0;
int matrix_row_counter = 0;
while(row_counter < result.rows)
{
for(int z = 0; z<result.cols; z++)
{
int index = labels.at<char>(row_counter+z, 0);
//cout << index << endl;
Vec3b center_channels(centers.at<char>(index,0),centers.at<char>(index,1), centers.at<char>(index,2));
result.at<Vec3b>(matrix_row_counter, z) = center_channels;
}
row_counter += result.cols;
matrix_row_counter++;
}
cout << "Labels " << labels.rows << " " << labels.cols << endl;
//cvtColor(src, gray, CV_BGR2GRAY);
//gray.convertTo(gray, CV_32F);
imshow("Result", result);
waitKey(0);
return 0;
}
总之,在计算快结束时,我只是得到一个黑色的图像。 你知道为什么吗? 奇怪的是,如果我在算法结束时初始化结果矩阵作为
Mat result(src.size(), src.type())
它将显示完全输入图像,没有任何分段。
特别是,我有两个疑惑:
1)是正确的躺在矩阵的每一行像素的RGB值调整我做的方式?有没有办法做到这一点没有循环?
2)k-means函数完成工作后,中心的内容究竟是什么?它是一个3列矩阵,它是否包含集群中心的RGB值?
感谢您的支持。下面
可能有重复的[是否有公式确定给定BGR值的整体颜色? (OpenCV和C++)](http://stackoverflow.com/questions/34734379/is-there-a-formula-to-determine-overall-color-given-bgr-values-opencv-and-c) – Miki
感谢回答。您提供的帖子解决了我的问题,给了我一个工作代码片段。无论如何,如果可能的话,我想知道我的错在哪里,因为我几乎肯定会在下次发生同样的错误。我能否对这两个疑问做出回答?感谢支持和抱歉,如果我问太多:) 我希望你不会把这个帖子当作经典的重复案例:) – ubisum
1)是的,正确的,但他们应该是浮动值。你可以在我的文章中看到如何做到没有循环。 2)是的,集群中心的BGR值以浮点数表示,需要转换为uchar。我现在不能更深入地看这个,但我的帖子应该清楚 – Miki