0
点赞
收藏
分享

微信扫一扫

OpenCV + CPP 系列(卌八)聚类与图像分割( KMeans)


文章目录

  • ​​KMeans- 聚类算法简介​​
  • ​​数据聚类代码示例​​
  • ​​图像聚类分割​​

KMeans- 聚类算法简介

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

常见的聚类方法有:划分式聚类方法(Partition-based Methods)基于密度的聚类方法(Density-based methods DBSCAN)层次化聚类方法(Hierarchical Methods) 等。

OpenCV + CPP 系列(卌八)聚类与图像分割( KMeans)_scala

关于更多理论请查看:​​​​​ 或者查看知乎的大佬:​​https://zhuanlan.zhihu.com/p/104355127​​​0

头文件 ​​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);
}

OpenCV + CPP 系列(卌八)聚类与图像分割( KMeans)_opencv_02

图像聚类分割

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);
}

OpenCV + CPP 系列(卌八)聚类与图像分割( KMeans)_kmeans_03


举报

相关推荐

0 条评论