当前位置 : 主页 > 编程语言 > java >

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

来源:互联网 收集:自由互联 发布时间:2022-07-17
文章目录 ​​KMeans- 聚类算法简介​​ ​​数据聚类代码示例​​ ​​图像聚类分割​​ KMeans- 聚类算法简介 无监督学习方法 分类问题,输入分类数目,初始化中心位置 硬分类方法


文章目录

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

KMeans- 聚类算法简介

  • 无监督学习方法
  • 分类问题,输入分类数目,初始化中心位置
  • 硬分类方法,以距离度量
  • 迭代分类为聚类
  • 常见的聚类方法有:划分式聚类方法(​​Partition-based Methods​​)、基于密度的聚类方法(​​Density-based methods​​ DBSCAN)、层次化聚类方法(​​Hierarchical Methods​​) 等。

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

    关于更多理论请查看:​​​​​ 或者查看知乎的大佬:​​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)_scala_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)_数据_03


    上一篇:Rust-OpenCV 图取与显示
    下一篇:没有了
    网友评论