K-Means分割数据(添加了详细注释)
在opencv中kmenas算法对应的教程,代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat img(500, 500, CV_8UC3);
img = Scalar::all(255);
RNG rng(12345);//随机数发生器
Scalar colorTab[] = {
Scalar(0,0,255),
Scalar(0,255,0),
Scalar(255,0,0),
Scalar(0,255,255),
Scalar(255,0,255)
};//用于数据点的颜色显示
int numCluster = rng.uniform(2, 5);//聚类个数4
printf("number of cluster is %d\n",numCluster);
int samplecount = rng.uniform(2, 1000);//随机生成samplecount个数据点591
Mat points(samplecount, 1, CV_32FC2);//samplecount个float类型的数据点,以矩阵的形势呈现
Mat labels;//kmeans算法后的label标签,里面存储了0,1,2,3四个像素值(有591个)(1x591)
Mat centors;//中心点
//生成随机数
for (int k = 0; k < numCluster; k++)
{
//初始化中心点
Point center;
center.x = rng.uniform(0,img.cols);
center.y = rng.uniform(0,img.rows);
//cout << center << endl;
//打印初始化中心点
//circle(img, center, 7, Scalar(0, 0, 255), -1, 8);
//Mat区块访问,只是创建数据头,改变同时改变
//这把数据点分成四份
Mat pointchunk = points.rowRange(k * samplecount / numCluster, k == numCluster - 1 ? samplecount : (k + 1) * samplecount / numCluster);
//rng.fill对每个数据点进行赋值,使得数据点具有不同的,CV_32FC2的像素值范围
//NORMAL是高斯分布,
rng.fill(pointchunk,RNG::NORMAL,Scalar(center.x,center.y),Scalar(img.cols*0.05,img.rows*0.05));
}
//以上产生了四个以中心点位均值的四个聚类数据
//cout << points << endl;
//作用:将原数组(矩阵)打乱
randShuffle(points,1,&rng);
//cout << points << endl;
//kmeans分类后,每个一类数据产生一个标签(0,1,2,3……)
kmeans(points,numCluster,labels,TermCriteria(TermCriteria::EPS+TermCriteria::COUNT,10,0.1),3,KMEANS_PP_CENTERS,centors);
//用不同值显示
for (int i = 0; i < samplecount; i++)
{
int index = labels.at<int>(i);
Point p = points.at<Point2f>(i);
circle(img, p, 2, colorTab[index], -1, 8);
}
//每个聚类数据中心点显示
for (size_t i = 0; i < centors.rows; i++)
{
float x = centors.at<float>(i, 0);
float y = centors.at<float>(i, 1);
circle(img,Point2f(x,y),8,colorTab[i],-1,8);
}
imshow("img", img);
waitKey(0);
return 0;
}