Kmeans又是一个以点到点距离为判断依据的算法,物理上的质心很好的形容了这个算法的目的。
说的没有做的理解深,还是实践一下。
#include "pch.h" #include <opencv2/core.hpp> #include <opencv2/imgproc.hpp> #include "opencv2/imgcodecs.hpp" #include <opencv2/highgui.hpp> #include <opencv2/ml.hpp> #include <iostream> using namespace std; using namespace cv; using namespace cv::ml; int main(int /*argc*/, char** /*argv*/) { const int CLUSTERS_COUNT = 3; //3个聚类中心 const int smpCount = 300; //300个样本点 const int height = 500; Mat img(height, height, CV_8UC3); RNG rng(10000); int k, i; Mat points(smpCount, 1, CV_32FC2), labels; vector<Point2f> centers; Scalar colorTab[] = { Scalar(0, 0, 255),//红 Scalar(0,255,0), //绿 Scalar(255,0,0), //蓝 }; for (k = 0;k < CLUSTERS_COUNT;k++) { //生成随机样本点 Point center; center.x = rng.uniform(0, height); center.y = rng.uniform(0, height); Mat pointChunk = points.rowRange(k*smpCount / CLUSTERS_COUNT, (k+1)*smpCount / CLUSTERS_COUNT); rng.fill(pointChunk, RNG::NORMAL, Scalar(center.x, center.y), Scalar(height*0.05, height*0.05)); } double compactness = kmeans(points, CLUSTERS_COUNT, labels, //执行kmeans算法 TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), 3, KMEANS_PP_CENTERS, centers); img = Scalar::all(0); for (i = 0;i < smpCount;i++) { int clusterIdx = labels.at<int>(i); Point ipt = points.at<Point2f>(i); circle(img, ipt, 2, colorTab[clusterIdx], FILLED, LINE_AA); //将样本点绘制到img上 } for (i = 0;i < (int)centers.size();i++) { Point2f c = centers[i]; circle(img, c, 40, colorTab[i], i, LINE_AA); //画一个聚类中心为中心,半径为40的圆 } imshow("kmeans", img); waitKey(0); return 0; }参考文章
https://blog.csdn.net/loveliuzz/article/details/78783773
https://zhuanlan.zhihu.com/p/27518705