opencv之聚类算法

来源:互联网 发布:五毒萝莉捏脸数据截图 编辑:程序博客网 时间:2024/06/14 03:58
算法介绍:
k-means 算法接受参数 k ,然后将事先输入的n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高,而不同聚类中的对象相似度较小。
聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。

K-means算法是最为经典的基于划分的聚类方法,是十大经典数据挖掘算法之一。
K-means算法的基本思想是:
以空间中k个点为中心进行聚类,对最靠近他们的对象归类。通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果。

假设要把样本集分为c个类别,算法描述如下:
(1)适当选择c个类的初始中心;
(2)在第k次迭代中,对任意一个样本,求其到c个中心的距离,将该样本归到距离最短的中心所在的类;
(3)利用均值等方法更新该类的中心值;
(4)对于所有的c个聚类中心,如果利用(2)(3)的迭代法更新后,值保持不变,则迭代结束,否则继续迭代。
该算法的最大优势在于简洁和快速。算法的关键在于初始中心的选择和距离公式。


//opencv库函数

CvRNG cvRNG( int64 seed CV_DEFAULT(-1))  //产生随机数种子,返回CvRNG
unsigned cvRandInt( CvRNG* rng );//产生随机的unsigned int值
void cvRandArr( CvRNG* rng, CvArr* arr, int dist_type, CvScalar param1, CvScalar param2 );//用随机数填充数组并更新 RNG 状态 
参考:http://www.opencv.org.cn/index.php/Cxcore%E6%95%B0%E7%BB%84%E6%93%8D%E4%BD%9C
void cvKMeans2( const CvArr* samples, int cluster_count,CvArr* labels, CvTermCriteria termcrit );//按照给定的类别数目对样本集合进行聚类
参考:http://www.opencv.org.cn/index.php/Cxcore%E5%85%B6%E5%AE%83%E6%B7%B7%E5%90%88%E5%87%BD%E6%95%B0
CvTermCriteria //迭代算法的终止准则
typedef struct CvTermCriteria {  int    type;  /* CV_TERMCRIT_ITER 和CV_TERMCRIT_EPS二值之一,或者二者的组合 */  int    max_iter; /* 最大迭代次数 */  double epsilon; /* 结果的精确性 */ } CvTermCriteria;

精简的测试代码
#include<cv.h>#include<highgui.h>#include<stdio.h>#include<malloc.h>#pragma comment(lib,"cv.lib")#pragma comment(lib,"cxcore.lib")#pragma comment(lib,"highgui.lib")#pragma comment(lib,"cvaux.lib")/***********************************************************************************  本程序是精简的聚类算法演示例程*  作者:xlh145*  博客:http://blog.csdn.net/xlh145/**********************************************************************************/#define MAX_POINTS 1000  /*最多产生1000个样本点*/#define CLASS_COUNT  5 /*生成5个分类*/int main(){CvRNG rng = cvRNG(-1);//产生随机数种子CvScalar color_tab[5];//定义5种颜色    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);IplImage* img = cvCreateImage(cvSize(500,500),8,3);//用于显示结果cvNamedWindow("result",1);//产生窗体//定义数组int sample_count = cvRandInt(&rng)%MAX_POINTS+1;//样本的数量int clusters_count = cvRandInt(&rng)%CLASS_COUNT+1;//分类的数量CvMat* points = cvCreateMat(sample_count,1,CV_32FC2);//双通道的数组,储存点的坐标CvMat * clusters = cvCreateMat(sample_count,1,CV_32SC1);//单通道的数组,储存分类的标识//创建样本数据for(int i=0;i<clusters_count;i++){CvPoint center; //每一个分类样本的中心CvMat ptemp;//临时的数组对象center.x = cvRandInt(&rng)%img->width;center.y = cvRandInt(&rng)%img->height;int count = sample_count/clusters_count;//均分每一个分类包含的样本cvGetRows(points,&ptemp,i*count,(i==clusters_count-1)?sample_count:(i+1)*count);//获取数组中的指定行数的指针 存储到ptemp中//按照正态分布随机化数组数据cvRandArr(&rng,&ptemp,CV_RAND_NORMAL,cvScalar(center.x,center.y,0,0),cvScalar(img->width*0.1,img->height*0.1,0,0));}//随机洗牌for(i = 0; i<sample_count/2;i++){CvPoint2D32f* p = (CvPoint2D32f*)points->data.fl;//数组的数据存放指针CvPoint2D32f* p1 = p+cvRandInt(&rng)%sample_count;CvPoint2D32f* p2 = p+cvRandInt(&rng)%sample_count;CvPoint2D32f t;CV_SWAP(*p1,*p2,t);} //Kmeans聚类 cvKMeans2(points,clusters_count,clusters,cvTermCriteria(CV_TERMCRIT_NUMBER|CV_TERMCRIT_ITER,10,1.0)); cvZero(img); //在图像上显示分类的点 for(i=0;i<sample_count;i++) { int id = clusters->data.i[i];//得到点的分类聚合ID CvPoint pt; pt.x = (int)points->data.fl[i*2+0]; pt.y = (int)points->data.fl[i*2+1]; cvCircle( img, pt, 2, color_tab[id], CV_FILLED, CV_AA, 0 ); }cvShowImage("result",img);cvWaitKey(0);//释放存储空间cvReleaseImage(&img);cvReleaseMat(&points);cvReleaseMat(&clusters);cvDestroyWindow("result");return 0;}


原创粉丝点击