首先介绍下OpenCV的聚类算法函数
int cvKMeans2(const CvArr* samples,int nclusters, CvArr* labels, CvTermCriteria termcrit,
int attempts=1, CvRNG* rng=0,int flags=0,
CvArr* centers=0,double* compactness=0);
samples:表示输入样本的浮点矩阵,每个样本一行(Mat型),必须浮点型,如对彩色图像进行聚类,每个通道一行,CV_32FC3;
nclusters:表示设定的聚类数量;
labels:表示输出整数向量:每个样本对应的类别标识,其范围为0- (cluster_count-1);
termcrit:表示终止条件(CV_TERMCRIT_ITER最大迭代次数终止,CV_TERMCRIT_EPS迭代到阈值终止,CV_TERMCRIT_ITER+CV_TERMCRIT_EPS两者都作为迭代终止条件)、最大迭代次数、结果精确性。;
attemps:表示尝试的次数,防止陷入局部最优;
flags:表示聚类中心的选取方式(KMEANS_RANDOM_CENTERS 随机选取,KMEANS_PP_CENTERS使用Arthur提供的算法,KMEANS_USE_INITIAL_LABELS使用初始标签);
centers:表示聚类后的类别中心。
下面列举应用实例代码(C++):
IplImage* img = cvLoadImage( “test.jpg”, 1);//加载三通道图像
int total= img->height*img->width;
int cluster_num = 5;//设置聚类数目
CvMat *row = cvCreateMat( img->height,img->width,CV_32FC3 );
cvConvert(img,row);//转一下类型!
m_clusters = cvCreateMat( total, 1, CV_32SC1 );
cvReshape(row,row,0,total);//修改矩阵的形状,每个数据一行,使row指向修改后的数据,不修改通道数
cvKMeans2( row, cluster_num, m_clusters,cvTermCriteria( CV_TERMCRIT_ITER, 100, 1.0 ));//聚类数据5,最大迭代次数终止
cvReshape(m_clusters,m_clusters,0,img->width);//聚类完的结果再reshape回来方便看
cvShowImage( "original", img );//显示原图
int i=0,j=0;
CvScalar s;
IplImage* resImg1 = cvCreateImage( cvSize(img->width,img->height), 8, 1 );//生成用来显示结果的图像
s=cvGet2D(img,i,j);
for(i=0;i<img->height;i++)
{
for (j=0;j<img->width;j++)
{
if (clusters->data.i[i*img->width+j]==0)//修改此处的“0”值,可以分别实现各个类的显示,比如设置聚类为5种,次数可以修改范围0-4
{
s.val[0]=255;
s.val[1]=255;
s.val[2]=255;
cvSet2D(resImg1,i,j,s);//注意循环顺序
}
else
{
s.val[0]=0;
s.val[1]=0;
s.val[2]=0;
cvSet2D(resImg1,i,j,s);
}
}
}
cvShowImage( "clusters1", resImg1 );
int key = cvWaitKey(0);
cvReleaseImage(&img);//记得释放内存
cvReleaseImage (&resImg1);
cvReleaseMat(&row);
cvReleaseMat(&clusters);
if (clusters->data.i[i*img->width+j]==0) —修改此处的“0”值,可以分别实现各个类的显示,比如设置聚类为5种,次数可以修改范围0-4,分别修改为0-4,分别查看分类效果: