图片来源于关注者提问,已私发,供参考
原图:

K-means分割后:

附上代码:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void Kmeans(Mat& img,Mat& r)
{
//定义图像分割颜色
Scalar color[]=
{
Scalar(0,0,255),
Scalar(0,255,0),
Scalar(255,0,0),
Scalar(0,255,255),
Scalar(255,0,255)
};
int w=img.cols;
int h=img.rows;
int d=img.channels();
int count=w*h;
int cluster_count=2;
Mat Points(count,d,CV_32F,Scalar(10));
Mat labels;//输出
Mat centers(cluster_count,1,Points.type());//存储聚类后的中心点
int index=0;
for(int i=0;i<h;i++)
{
for(int j=0;j<w;j++)
{
index=i*w+j;//每个像素点的索引值,一行一行的遍历
Vec3b bgr=img.at<Vec3b>(i,j);
Points.at<float>(index,0)=static_cast<int>(bgr[0]);
Points.at<float>(index,1)=static_cast<int>(bgr[1]);
Points.at<float>(index,2)=static_cast<int>(bgr[2]);
}
}
//k均值
TermCriteria criteria=
TermCriteria(TermCriteria::EPS+TermCriteria::COUNT,10,0.1);
kmeans(Points,cluster_count,labels,criteria,3,KMEANS_PP_CENTERS,centers);
for(int i=0;i<h;i++)
{
for(int j=0;j<w;j++)
{
index=i*w+j;//每个像素点的索引值,一行一行的遍历
int label=labels.at<int>(index,0);
r.at<Vec3b>(i,j)[0]=color[label][0];
r.at<Vec3b>(i,j)[1]=color[label][1];
r.at<Vec3b>(i,j)[2]=color[label][2];
}
}
/最后聚类中心点的坐标
for(int i=0;i<centers.rows;i++)
{
int x=centers.at<float>(i,0);
int y=centers.at<float>(i,1);
cout<<"centers: "<<i<<" "<<x<<" "<<y<<" "<<endl;
}
}
int main(int argc,char* argv[])
{
Mat img=imread(argv[1],1);
if(img.empty())
{
cout<<"not img"<<endl;
return -1;
}
imshow("img",img);
waitKey(0);
Mat r=Mat::zeros(img.size(),img.type());
Kmeans( img, r);
imshow("result",r);
waitKey(0);
return 0;
}TermCriteria::TermCriteria - 构造函数
TermCriteria::TermCriteria
(
int type,
int maxCount,
double epsilon
)参数说明: type - 终止条件的类型:TermCriteria::COUNT,TermCriteria::EPS或 TermCriteria::COUNT + TermCriteria::EPS maxCount - 要计算的最大迭代次数或元素 epsilon - 迭代算法停止的所需精度或参数更改 criteria - 终止标准(已弃用的CvTermCriteria格式)。
kmeans - 查找聚类的中心,并对聚类周围的输入样本进行分组
double kmeans
(
InputArray data,
int K,
InputOutputArray bestLabels,
TermCriteria criteria,
int attempts,
int flags,
OutputArray centers=noArray()
)
参数说明: data - 用于聚类的数据。需要具有浮点坐标的N维点数组。此数组的示例 可以是:
- Mat points(count, 2, CV_32F);
- Mat points(count, 1, CV_32FC2);
- Mat points(1, count, CV_32FC2);
- std::vector<cv::Point2f> points(sampleCount);K - 用来分割集合的集群数。 labels - 输入/输出整数数组,用于存储每个样本的聚类索引。 criteria - 算法终止标准,即最大迭代次数和/或所需精度。精度被指定为criteria.epsilon。一旦每个聚类中心在某个迭代上移动的距离小于criteria.epsilon,该算法就会停止。 termcrit - 算法终止标准,即最大迭代次数和/或所需精度。 attempts - 用于指定使用不同的初始标签执行算法的次数的标志。该算法返回产生最佳紧凑性的标签(请参见最后一个功能参数)。 flags - 可以采用以下值的标志 KMEANS_RANDOM_CENTERS - 在每次尝试中选择随机的初始中心。 KMEANS_PP_CENTERS - 使用Arthur和Vassilvitskii进行的kmeans ++中心初始化。 KMEANS_USE_INITIAL_LABELS - 在第一次(可能也是唯一的)尝试期间,请使用用户提供的标签,而不要从初始中心进行计算。对于第二次或更进一步的尝试,请使用随机或半随机中心。使用KMEANS _ * _ CENTERS标志之一来指定确切的方法 .