알고리즘

Kmeans 이해하기

목가 2010. 1. 7. 19:36
반응형

 그냥 메뉴얼에 있는 것을 가져온 것인데 주의 사항이 sample의 row가 1이라는 사실입니다.  

KMeans2

Splits set of vectors by given number of clusters

(요것이 하는 일)

 

void cvKMeans2( const CvArr* samples, int cluster_count,
                CvArr* labels, CvTermCriteria termcrit );

samples

Floating-point matrix of input samples, one row per sample.

cluster_count

Number of clusters to split the set by.

labels

Output integer vector storing cluster indices for every sample.

termcrit

Specifies maximum number of iterations and/or accuracy (distance the centers move by between the subsequent iterations).

The function cvKMeans2 implements k-means algorithm that finds centers of cluster_count clusters and groups the input samples around the clusters. On output labels(i) contains a cluster index for sample stored in the i-th row of samples matrix.

 

Pasted from <http://www.cs.indiana.edu/cgi-pub/oleykin/website/OpenCVHelp/ref/OpenCVRef_CxCore.htm>

 

 

위에서 언급한 바와 같이 clustering sample dimension 1-row 이다,

        int k, cluster_count = cvRandInt(&rng)%MAX_CLUSTERS + 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 );

 

 

 

Example. Clustering random samples of multi-gaussian distribution with k-means

 

Pasted from <http://www.cs.indiana.edu/cgi-pub/oleykin/website/OpenCVHelp/ref/OpenCVRef_CxCore.htm>

다음의 코드를 돌리면 맨 아래의 그림이 나옵니다.

랜덤 함수로 생성된 점들을 5개로 clustering 한 것입니다.

색깔로 구분해 주고 있습니다.

OpenCV 안의 예제입니다. 이것을 분석해 보시면 금방 알 수 있습니다.

 

//general

#include <stdio.h>

 

//opencv

#include "cv.h"

#include "cxcore.h"

#include "highgui.h"

 

void main( int argc, char** argv )

{

    #define MAX_CLUSTERS 5

    CvScalar color_tab[MAX_CLUSTERS];

    IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );

    CvRNG rng = cvRNG(0xffffffff); // ??? why???

   

    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);

 

    cvNamedWindow( "clusters", 1 );

 

    for(;;)

    {

        int k, cluster_count = cvRandInt(&rng)%MAX_CLUSTERS + 1; // (MAX_CLUSTER = 5)

        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 sample from multigaussian 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 );

        }

 

        cvKMeans2( points, cluster_count, clusters,

                   cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0 ));

 

        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);

        if( key == 27 ) // 'ESC'

            break;

    }

}

반응형