KMeans- 聚类算法简介
  1. 无监督学习方法
  2. 分类问题,输入分类数目,初始化中心位置
  3. 硬分类方法,以距离度量
  4. 迭代分类为聚类

常见的聚类方法有:划分式聚类方法(Partition-based Methods)基于密度的聚类方法(Density-based methods DBSCAN)层次化聚类方法(Hierarchical Methods) 等。
在这里插入图片描述

关于更多理论请查看:https://blog.csdn.net/wsp_1138886114/article/details/80475981
或者查看知乎的大佬:https://zhuanlan.zhihu.com/p/104355127
关于代码示例请查看:https://blog.csdn.net/wsp_1138886114/article/details/80893941
关于案例代码请查看:https://blog.csdn.net/wsp_1138886114/article/details/80673450

头文件 machine_learning_all.h

#pragma once
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;


class Machine_learning{
public:
	void KMeans_data_demo();
};

主函数main.cpp

#include "machine_learning_all.h"


int main(int argc, char** argv) {
	const char* input_path = "D:\\Desktop\\meinv3.png";
	Mat src = imread(input_path);
	if (src.empty()) {
		cout << "Read image failed!" << endl;
		return -1;
	}

	Machine_learning ml;
	ml.KMeans_data_demo();
	ml.KMeans_image_demo(src);

	imshow("src", src);
	waitKey(0);
	destroyAllWindows();
	return 0;
}
数据聚类代码示例
void Machine_learning::KMeans_data_demo() {
	Mat img = Mat::zeros(450, 450, CV_8UC3);
	RNG rng(123123);

	Scalar colorTab[] = {
		Scalar(0,0,255),
		Scalar(0,255,0),
		Scalar(255,0,0),
		Scalar(0,255,255),
		Scalar(255,0,255),
		Scalar(255,255,0) 
	};

	int numCluster = rng.uniform(3, 5);
	cout << "Number of cluster: " << numCluster << endl;

	int sampleCount = rng.uniform(500, 1000);
	Mat points(sampleCount, 1, CV_32FC2); //生成数据 (height,width)=(sampleCount,1)
	Mat labels;
	Mat centers;
	cout << "points.size():" << points.size() << endl;

	//生成随机数
	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.5, img.rows * 0.5));
		randShuffle(points, 1, &rng);
	}

	//聚类
	kmeans(points, numCluster, labels, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 0.1), 3, KMEANS_PP_CENTERS, centers);

	//使用不同的颜色区分类别
	img = Scalar::all(0);
	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, 0);
	}

	//每个聚类的中心来绘图
	for (int i = 0; i < centers.rows; i++) {
		int x = centers.at<float>(i, 0);
		int y = centers.at<float>(i, 1);
		cout << "[x, y] = " << x << ", " << y << endl;
		circle(img, Point(x, y), 40, colorTab[i], 1, LINE_AA);
	}
	imshow("KMeans-demo", img);
}

在这里插入图片描述

图像聚类分割
void Machine_learning::KMeans_image_demo(Mat& src) {
	Scalar colorTab[] = {
		Scalar(0,0,255),
		Scalar(0,255,0),
		Scalar(255,0,0),
		Scalar(0,255,255),
		Scalar(255,0,255),
		Scalar(255,255,0)
	};

	int width = src.cols;
	int height = src.rows;
	int dims = src.channels();

	// 初始化定义
	int sampleCount = width * height;
	int clusterCount = 3;
	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++) {
		Vec3b* bgr_ptr = src.ptr<Vec3b>(row);
		for (int col = 0; col < width; col++) {
			index = row * width + col;
			points.at<float>(index, 0) = static_cast<int>(bgr_ptr[col][0]);
			points.at<float>(index, 1) = static_cast<int>(bgr_ptr[col][1]);
			points.at<float>(index, 2) = static_cast<int>(bgr_ptr[col][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++) {
		Vec3b* result_ptr = result.ptr<Vec3b>(row);
		for (int col = 0; col < width; col++) {
			index = row * width + col;
			int label = labels.at<int>(index, 0);
			result_ptr[col][0] = colorTab[label][0];
			result_ptr[col][1] = colorTab[label][1];
			result_ptr[col][2] = colorTab[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 << "[x, y] = " << x << ", " << y << endl;
		// 聚类中心为:颜色的中心
		//[x, y] = 194, 211
		//[x, y] = 49, 43
		//[x, y] = 146, 149
	}
	imshow("KMeans Image", result);
}

在这里插入图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐