在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"#includeint 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 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 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 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;}
效果图如下,
恩,先就这样。