Opencv Kmeans聚类算法

k-means 算法接受输入量 k ;然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小

1. 算法基本步骤

(1) 从 n个数据对象任意选择 k 个对象作为初始聚类中心;

(2) 根据每个聚类对象的均值(中心对象),计算每个对象与这些中心对象的距离;并根据最小距离重新对相应对象进行划分;

(3) 重新计算每个(有变化)聚类的均值(中心对象);

(4) 计算标准测度函数,当满足一定条件,如函数收敛时,则算法终止;如果条件不满足则回到步骤(2)。

 

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

下面还用到了函数CvMat* cvReshape( const CvArr* arr, CvMat* header, int new_cn, int new_rows=0 );

arr 输入的数组. header 被添充的矩阵头 new_cn 新的通道数.new_cn = 0 意味着不修改通道数 new_rows 新的行数。

 如果new_rows = 0保持原行数不修改否则根据 new_cn 值修改输出数组 函数 cvReshape 初始化 CvMat 头header 以便于让头指向修改后的形状(但数据保持原样)-也就是说修改通道数,修改行数或者两者者改变。

 

#include "cxcore.h"
#include "highgui.h"

void main()
{

	IplImage* img = cvLoadImage( "test.jpg", 1);//三通道图像
	int total= img->height*img->width;
	int cluster_num = 2;
	CvMat *row = cvCreateMat( img->height,img->width,CV_32FC3 );
	cvConvert(img,row);//转一下类型!
	CvMat *clusters = cvCreateMat( total, 1, CV_32SC1 );
	cvReshape(row,row,0,total);//修改矩阵的形状,每个数据一行,使row指向修改后的数据,不修改通道数
	cvKMeans2( row, cluster_num, clusters,cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0 ));
	cvReshape(clusters,clusters,0,img->width);//聚类完的结果再reshape回来方便看

	int i=0,j=0;
	CvScalar s;
	IplImage* resImg = 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]==1)
			{
				s.val[0]=255;
				s.val[1]=255;
				s.val[2]=255;
				cvSet2D(resImg,i,j,s);//注意循环顺序
			}
			else
			{
				s.val[0]=0;
				s.val[1]=0;
				s.val[2]=0;
				cvSet2D(resImg,i,j,s);
			}
		}
	}
	cvShowImage( "original", img );
	cvShowImage( "clusters", resImg );

	int key = cvWaitKey(0);

	cvReleaseImage(&img);//记得释放内存
	cvReleaseImage (&resImg);
	cvReleaseMat(&row);
	cvReleaseMat(&clusters);
}


 结果如下所示:

Opencv Kmeans聚类算法_第1张图片

你可能感兴趣的:(opencv,聚类,kmeans)