Machine Learning(1)——k-means算法

在OpenCV Maching Learning部分,实现了一些经典的机器学习算法,并且每个算法都有相应的例子,所以我觉得可以从这里开始学习机器学习算法。

K-means算法应该是比较简单的机器学习算法,就先从这个开始学习。

K-means 算法是很典型的基于距离的聚类算法 。从二维图像的例子来看,图像上有很多个点,为了将这些点按他们相近的距离分成一簇一簇的,假设要分成k簇,k-means算法步骤如下,

a.  随机地选取k个点作为中心,

b.  计算每个点到这些中心的距离,将这个点归属于离它最近的中心,这样就得到了k个簇。因为是随机选取的中心,会有一些点分配到错误的中心上。

c.  根据得到的簇重新计算出它的中心,那么属于某个簇的点到它中心的距离就比较平均。

d.  重复b~c,直到收敛。

上图中可以看到,一开始随机选取的中心,有可能使一些点错误地放到其它簇。但在迭代过程中,它会改变它所属的簇,最后归属到正确的簇。

下面是OpenCV里面的代码,相较于learning OpenCV上的代码,添加了cluster个数和sample个数的输出,修复了按esc键不能退出的bug。

 

View Code
// example in book leanring OpenCV, machine learning, k-means algorithn

// good site for OpenCV examples, http://nashruddin.com/OpenCV_Examples_Part_2

#include "cxcore.h"
#include "highgui.h"

#include <cstdio>

int main(int argc, char** argv)
{
    #define MAX_CLUSTER 5
    CvScalar color_tab[MAX_CLUSTER];
    IplImage* img = cvCreateImage(cvSize(500,500),8,3);
    CvRNG rng = cvRNG(0xffffffff);
    
    color_tab[0] = CV_RGB(255,0,0);
    color_tab[1] = CV_RGB(0,255,0);
    color_tab[2] = CV_RGB(100,100,255);
    color_tab[3] = CV_RGB(255,0,255);
    color_tab[4] = CV_RGB(255,255,0);

    for(;;)
    {
        int k, cluster_count = cvRandInt(&rng)%MAX_CLUSTER+1;
        int i, sample_count = cvRandInt(&rng)%1000+1;
        CvMat* points = cvCreateMat(sample_count,1,CV_32FC2);
        CvMat* clusters = cvCreateMat(sample_count,1,CV_32SC1);
        
        /* generate random samples */
        /* gaussian distribution */
        for(k=0;k<cluster_count;k++)
        {
            CvPoint center;
            CvMat point_chunk;
            center.x = cvRandInt(&rng)%img->width;
            center.y = cvRandInt(&rng)%img->height;
            cvGetRows(points,&point_chunk,
                    k*sample_count/cluster_count,
                    k==cluster_count-1?sample_count:
                    (k+1)*sample_count/cluster_count);
            cvRandArr(&rng,&point_chunk,CV_RAND_NORMAL,
                    cvScalar(center.x,center.y,0,0),
                    cvScalar(img->width/6,img->height/6,0,0));
        }

        /* shuffle samples */
        for(i=0;i<sample_count/2;i++)
        {
            CvPoint2D32f* pt1 = (CvPoint2D32f*)points->data.fl + 
                cvRandInt(&rng)%sample_count;
            CvPoint2D32f* pt2 = (CvPoint2D32f*)points->data.fl + 
                cvRandInt(&rng)%sample_count;
            CvPoint2D32f temp;
            CV_SWAP(*pt1,*pt2,temp);
        }

        printf("cluster_count: %d\nsample_count:%d\n\n",cluster_count,sample_count);    

        cvKMeans2(points,cluster_count,clusters,
                cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER,100,0.01));
        cvZero(img);
        for(i=0;i<sample_count;i++)
        {
            CvPoint2D32f pt = ((CvPoint2D32f*)points->data.fl)[i];
            int cluster_idx = clusters->data.i[i];
            cvCircle(img,cvPointFrom32f(pt),2,
                    color_tab[cluster_idx],CV_FILLED);
        }
        cvReleaseMat(&points);
        cvReleaseMat(&clusters);
    
        cvShowImage("clusters",img);

        int key = cvWaitKey(0);
        key = key&0x000000FF;
        //printf("the key pressed:%d\n",key);
        if(key==27)
            break;
    }

    return 0;
}

 

效果图如下,

恩,先就这样。

posted @ 2012-11-03 19:12  Frandy.CH  阅读(561)  评论(0编辑  收藏  举报