본문 바로가기
알고리즘

Kmeans 이해하기

by 목가 2010. 1. 7.
반응형

 그냥 메뉴얼에 있는 것을 가져온 것인데 주의 사항이 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;

    }

}

반응형

댓글