KMeans方法概述
- 无监督学习方法
- 分类问题,输入分类数目,初始化中心位置
- 硬分类方法,以距离度量
- 迭代分类为聚类
OpenCV相关API
double cv::kmeans(InputArray data,
int k,
inputOutputArray bestLabels,
TermCriteria criteria,
int attempts,
int flags,
OutputArray centers=
)
KMeans方法-数据聚类代码
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc,char** argv){
Mat img(500,500,CV_8UC3);
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);
printf("number of clusters:%d\n",numCluster);
int sampleCount=rng.uniform(2,1000);
Mat points(sampleCount,1,CV_32FC2);
Mat labels;
Mat centers;
//生成随机数
for(int k=0;k<numCluster;k++){
Point center;
center.x=rng.uniform(0,img.cols);
center.y=rng.uniform(0,img.rows);
Mat pointChunk=points.rowRange(k*sampleCount/numCluster,k==numCluster-1?sampleCount:(k+1)*sampleCount/numCluster);
rng.fill(pointChunk,RNG::NORMAL,Scalar(center.x,center.y),Scalar(img.cols*0.05,img.rows*0.05));
}
randShuffle(points,1,&rng);
//使用Keans
kmeans(points,numCluster,labels,TermCriteria(TermCriteria::EPS+TermCriteria::COUNT,10,0.1),3,KMEANS_PP_CENTERS,centers);
//Mat colorTab[];
//用不同颜色显示分类
img=Scalar::all(255);
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(int i=0;i<centers.rows;i++){
int x=centers.at<float>(i,0);
int y=centers.at<float>(i,1);
printf("c.x=%d,c.y=%d",x,y);
circle(img,Point(x,y),40,colorTab[i],1,0);
}
imshow("KMeans-Data-Demo",img);
waitKey(0);
return 0;
}
KMeans方法-图像分割代码
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main(int argc,char** argv){
Mat src=imread("E:/opencv/zzz/hbz.jpg");
if(src.empty()){
printf("could not load image...\n");
return -1;
}
namedWindow("input image",CV_WINDOW_AUTOSIZE);
imshow("input image",src);
Scalar colorTab[]={
Scalar(0,0,255),
Scalar(0,255,0),
Scalar(255,0,0),
Scalar(0,255,255),
Scalar(255,0,255),
};
int width=src.cols;
int height=src.rows;
int dims=src.channels();
//初始化定义
int sampleCount=width*height;
int clusterCount=4;
Mat points(sampleCount,dims,CV_32F,Scalar(10));
Mat labels;
Mat centers(clusterCount,1,points.type());
//RGB数据转换样本数据
int index=0;
for(int row=0;row<height;row++){
for(int col=0;col<width;col++){
index=row*width+col;
Vec3b bgr=src.at<Vec3b>(row,col);
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-Means
TermCriteria criteria=TermCriteria(TermCriteria::EPS+TermCriteria::COUNT,10,0.1);
kmeans(points,clusterCount,labels,criteria,3,KMEANS_PP_CENTERS,centers);
//显示图像分割结果
Mat result=Mat::zeros(src.size(),src.type());
for(int row=0;row<height;row++){
for(int col=0;col<width;col++){
index=row*width+col;
int label=labels.at<int>(index,0);
result.at<Vec3b>(row,col)[0]=colorTab[label][0];
result.at<Vec3b>(row,col)[1]=colorTab[label][1];
result.at<Vec3b>(row,col)[2]=colorTab[label][2];
}
}
imshow("KMeans image Segmentation Demo",result);
waitKey(0);
return 0;
}
注:笔记来源观看此教程的记录:
https://www.bilibili.com/video/BV1Q54y1z7kz?p=93