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

posted on 2018-02-05 12:57  yjbjingcha  阅读(369)  评论(0编辑  收藏  举报

导航