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目录下)

  • 相关阅读:
    POJ 1328 Radar Installation
    POJ 1700 Crossing River
    POJ 1700 Crossing River
    poj 3253 Fence Repair (贪心,优先队列)
    poj 3253 Fence Repair (贪心,优先队列)
    poj 3069 Saruman's Army(贪心)
    poj 3069 Saruman's Army(贪心)
    Redis 笔记与总结2 String 类型和 Hash 类型
    数据分析方法有哪些_数据分析方法
    数据分析方法有哪些_数据分析方法
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/8417134.html
Copyright © 2011-2022 走看看