文章目录 KMeans- 聚类算法简介 数据聚类代码示例 图像聚类分割 KMeans- 聚类算法简介 无监督学习方法 分类问题,输入分类数目,初始化中心位置 硬分类方法
文章目录
- KMeans- 聚类算法简介
- 数据聚类代码示例
- 图像聚类分割
KMeans- 聚类算法简介
常见的聚类方法有:划分式聚类方法(Partition-based Methods)、基于密度的聚类方法(Density-based methods DBSCAN)、层次化聚类方法(Hierarchical Methods) 等。
关于更多理论请查看: 或者查看知乎的大佬:https://zhuanlan.zhihu.com/p/1043551270
头文件 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);
}