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

实现效果如下:
k-means算法MATLAB和opencv代码_第1张图片

上图图一是一张帅哥刘德华的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算法MATLAB和opencv代码_第2张图片
这是产生随机的样本点,再用k-means进行聚类。
代码较为简陋,如有问题欢迎交流~

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

2、opencv学习例程(在opencv安装路径的source文件夹下)

你可能感兴趣的:(代码,matlab,kmeans)