You can vectorize your image so that each line is a set of RGB, rather than using cv::kmeans for a cluster, for example:
std::vector<cv::Mat> imgRGB; cv::split(img,imgRGB); int k=5; int n = img.rows *img.cols; cv::Mat img3xN(n,3,CV_8U); for(int i=0;i!=3;++i) imgRGB[i].reshape(1,n).copyTo(img3xN.col(i)); img3xN.convertTo(img3xN,CV_32F); cv::Mat bestLables; cv::kmeans(img3xN,k,bestLables,cv::TermCriteria(),10,cv::KMEANS_RANDOM_CENTERS ); bestLables= bestLables.reshape(0,img.rows); cv::convertScaleAbs(bestLables,bestLables,int(255/k)); cv::imshow("result",bestLables); cv::waitKey();
source share