zoukankan      html  css  js  c++  java
  • k-means算法MATLAB和opencv代码

    上一篇博客写了k-means聚类算法和改进的k-means算法。这篇博客就贴出相应的MATLAB和C++代码。

    下面是MATLAB代码,实现用k-means进行切割:

        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        功能:实现怎样利用Kmeans聚类实现图像的切割。
        时间:2015-07
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
        function kmeans_segmentation()
        clear;close all;clc;
        %% 读取測试图像
        im = imread('city.jpg');
        imshow(im), title('Imput image');  %%转换图像的颜色空间得到样本
        cform = makecform('srgb2lab');
        lab = applycform(im,cform);
        ab = double(lab(:,:,2:3));
        nrows = size(lab,1); ncols = size(lab,2);
        X = reshape(ab,nrows*ncols,2)';
              figure, scatter(X(1,:)',X(2,:)',3,'filled'),title('image 2');  box on; %显示颜色空间转换后的二维样本空间分布
        %% 对样本空间进行Kmeans聚类
        k = 5; % 聚类个数
        max_iter = 100; %最大迭代次数
        [centroids, labels] = run_kmeans(X, k, max_iter); 
    
        %% 显示聚类切割结果
        figure, scatter(X(1,:)',X(2,:)'3,labels,'filled'),title('image 3'); %显示二维样本空间聚类效果
        hold on; scatter(centroids(1,:),centroids(2,:), 60,'r','filled')
        hold on; scatter(centroids(1,:),centroids(2,:),30,'g','filled')
        box on; hold off;
        %print -dpdf 2D2.pdf
    
        pixel_labels = reshape(labels,nrows,ncols);
        rgb_labels = label2rgb(pixel_labels);
        figure, imshow(rgb_labels), title('Segmented Image');
        %print -dpdf Seg.pdf
        end
    
        function [centroids, labels] = run_kmeans(X, k, max_iter)
        % 该函数实现Kmeans聚类
        % 输入參数:
        %                   X为输入样本集,dxN
        %                   k为聚类中心个数
        %                   max_iter为kemans聚类的最大迭代的次数
        % 输出參数:
        %                   centroids为聚类中心 dxk
        %                   labels为样本的类别标记
        %% 採用K-means++算法初始化聚类中心
        centroids = X(:,1+round(rand*(size(X,2)-1)));
        labels = ones(1,size(X,2));
        for i = 2:k
            D = X-centroids(:,labels);
            D = cumsum(sqrt(dot(D,D,1)));
            if D(end) == 0, centroids(:,i:k) = X(:,ones(1,k-i+1)); return; end
            centroids(:,i) = X(:,find(rand < D/D(end),1));
            [~,labels] = max(bsxfun(@minus,2*real(centroids'*X),dot(centroids,centroids,1).'));
          end
    
        %% 标准Kmeans算法
         for iter = 1:max_iter
            for i = 1:k, l = labels==i; centroids(:,i) = sum(X(:,l),2)/sum(l); end
            [~,labels] = max(bsxfun(@minus,2*real(centroids'*X),dot(centroids,centroids,1).'),[],1);
    
        end
        end

    实现效果例如以下:
    这里写图片描写叙述

    上图图一是一张帅哥刘德华的JPG格式相片。图二是将RGB空间的图片转换为LAB空间的分布图;图三是对LAB空间的图像进行聚类,一共三类,图四是将聚类后的LAB图转换为原来的RGB图。

    下面是VS+opencv实现:

    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/core/core.hpp"
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    int main( int /*argc*/, char** /*argv*/ )
    {
        const int MAX_CLUSTERS = 5;
        Scalar colorTab[] =
        {
            Scalar(0, 0, 255),
            Scalar(0,255,0),
            Scalar(255,100,100),
            Scalar(255,0,255),
            Scalar(0,255,255)
        };
    
        Mat img(500, 500, CV_8UC3);
        RNG rng(12345);
    
        for(;;)
        {
            int k, clusterCount = rng.uniform(2, MAX_CLUSTERS+1);
            int i, sampleCount = rng.uniform(1, 1001);
            Mat points(sampleCount, 2, CV_32F), labels;
    
            clusterCount = MIN(clusterCount, sampleCount);
            Mat centers;
    
            /* generate random sample from multigaussian distribution */
            for( k = 0; k < clusterCount; k++ )
            {
                Point center;
                center.x = rng.uniform(0, img.cols);
                center.y = rng.uniform(0, img.rows);
                Mat pointChunk = points.rowRange(k*sampleCount/clusterCount,
                k == clusterCount - 1 ?

    sampleCount :(k+1)*sampleCount/clusterCount); rng.fill(pointChunk, CV_RAND_NORMAL, Scalar(center.x, center.y), Scalar(img.cols*0.05, img.rows*0.05)); } randShuffle(points, 1, &rng); kmeans(points, clusterCount, labels, TermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0),3, KMEANS_PP_CENTERS, centers); img = Scalar::all(0); for( i = 0; i < sampleCount; i++ ) { int clusterIdx = labels.at<int>(i); Point ipt = points.at<Point2f>(i); circle( img, ipt, 2, colorTab[clusterIdx], CV_FILLED, CV_AA ); } imshow("clusters", img); char key = (char)waitKey(); if( key == 27 || key == 'q' || key == 'Q' ) break; } return 0; }

    这里写图片描写叙述
    这是产生随机的样本点,再用k-means进行聚类。
    代码较为简陋。如有问题欢迎交流~

    參考资料:
    1、视觉机器学习20讲

    2、opencv学习例程(在opencv安装路径的source目录下)

  • 相关阅读:
    COCO2018 目标检测
    最小生成树[摘录自严长生老师的网站]
    PANet训练自己的数据(VIA标注)
    图的遍历[摘录自严长生老师的网站]
    图的链式存储(邻接表)【摘录自严长生老师的网站】
    Android写入到mysql里的中文总是乱码?
    Mac 当xampp里mysql无法启动的解决办法
    【代码段】Android Studio使用DatePicker选择日期
    Android jdbc连接mysql报错解决方案 (Communications link failure)
    绝命毒师口语精析(4)
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/8417134.html
Copyright © 2011-2022 走看看