学习OpenCV——Kmean(C++)

从前也练习使用过OpenCV的Kmean算法,但是那版本低,而且也是基于C的开发。这两天由于造论文的需要把它重新翻出来在研究一下C++,发现有了些改进

kmeans

C++: doublekmeans(InputArraydata, int K, InputOutputArray bestLabels, TermCriteriacriteria, int attempts, int flags, OutputArraycenters=noArray() )
data:输入样本,要分类的对象,浮点型,每行一个样本(我要对颜色分类则每行一个像素);
K:    类型数目;
bestLabels: 分类后的矩阵,每个样本对应一个类型label;
TermCriteria criteria:结束条件(最大迭代数和理想精度)
int attempts:根据最后一个参数确定选取的最理想初始聚类中心(选取attempt次初始中心,选择compactness最小的);
int flags :

Flag that can take the following values:

  • KMEANS_RANDOM_CENTERS Select random initial centers in each attempt.
  • KMEANS_PP_CENTERS Use kmeans++ center initialization by Arthur and Vassilvitskii [Arthur2007].
  • KMEANS_USE_INITIAL_LABELS During the first (and possibly the only) attempt, use the user-supplied labels instead of computing them from the initial centers. For the second and further attempts, use the random or semi-random centers. Use one of KMEANS_*_CENTERS flag to specify the exact method.

centers输出聚类中心,每行一个中心(第一列是聚类中心,但是还有其他列,这里不太明白,大家谁懂,求科普啊!~~)

compactness 测试初始中心是否最优

                         

 

上代码:

 
 
#include <string>
#include <iostream>
#include <math.h>
#include <vector>
#include <map>

#include "opencv/cv.h"
#include "opencv/highgui.h"
#include "opencv/cxcore.h"

#define ClusterNum (6)

using namespace cv;
using namespace std;

string filename="D:/demo1.jpg";

Mat clustering(Mat src)
{
	int row = src.rows;
	int col = src.cols;
	unsigned long int size = row*col;

	Mat clusters(size, 1, CV_32SC1);	//clustering Mat, save class label at every location;

	//convert src Mat to sample srcPoint.
	Mat srcPoint(size, 1, CV_32FC3);	

	Vec3f* srcPoint_p = (Vec3f*)srcPoint.data;//////////////////////////////////////////////
	Vec3f* src_p = (Vec3f*)src.data;
	unsigned long int i;

	for(i = 0;i < size; i++)
	{
		*srcPoint_p = *src_p;
		srcPoint_p++;
		src_p++;
	}
	Mat center(ClusterNum,1,CV_32FC3);
	double compactness;//compactness to measure the clustering center dist sum by different flag
	compactness = kmeans(srcPoint, ClusterNum, clusters,
		cvTermCriteria (CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 0.1),ClusterNum,
		KMEANS_PP_CENTERS , center);

	cout<<"center row:"<<center.rows<<" col:"<<center.cols<<endl;
	for (int y = 0; y < center.rows; y++) 
	{
		Vec3f* imgData = center.ptr<Vec3f>(y);
		for (int x = 0; x < center.cols; x++)
		{
			cout<<imgData[x].val[0]<<" "<<imgData[x].val[1]<<" "<<imgData[x].val[2]<<endl;
		}
		cout<<endl;
	}


	double minH,maxH;
	minMaxLoc(clusters, &minH, &maxH);			//remember must use "&"
	cout<<"H-channel min:"<<minH<<" max:"<<maxH<<endl;

	int* clusters_p = (int*)clusters.data;
	//show label mat
	Mat label(src.size(), CV_32SC1);
	int* label_p = (int*)label.data;
	//assign the clusters to Mat label
	for(i = 0;i < size; i++)
	{
		*label_p = *clusters_p;
		label_p++;
		clusters_p++;
	}

	Mat label_show;
	label.convertTo(label_show,CV_8UC1);
	normalize(label_show,label_show,255,0,CV_MINMAX);
	imshow("label",label_show);



	map<int,int> count;		//map<id,num>
	map<int,Vec3f> avg;		//map<id,color>

	//compute average color value of one label
	for (int y = 0; y < row; y++) 
	{
		const Vec3f* imgData = src.ptr<Vec3f>(y);
		int* idx = label.ptr<int>(y);
		for (int x = 0; x < col; x++)
		{

			avg[idx[x]] += imgData[x];
			count[idx[x]] ++;
		}
	}
	//output the average value (clustering center)
	//计算所得的聚类中心与kmean函数中center的第一列一致,
	//以后可以省去后面这些繁复的计算,直接利用center,
	//但是仍然不理解center的除第一列以外的其他列所代表的意思
	for (i = 0; i < ClusterNum; i++)
	{
		avg[i] /= count[i];
		if (avg[i].val[0]>0&&avg[i].val[1]>0&&avg[i].val[2]>0)
		{
			cout<<i<<": "<<avg[i].val[0]<<" "<<avg[i].val[1]<<" "<<avg[i].val[2]<<" count:"<<count[i]<<endl;

		}
	}
	//show the clustering img;
	Mat showImg(src.size(),CV_32FC3);
	for (int y = 0; y < row; y++) 
	{
		Vec3f* imgData = showImg.ptr<Vec3f>(y);
		int* idx = label.ptr<int>(y);
		for (int x = 0; x < col; x++)
		{
			int id = idx[x];
			imgData[x].val[0] = avg[id].val[0];
			imgData[x].val[1] = avg[id].val[1];
			imgData[x].val[2] = avg[id].val[2];
		}
	}
	normalize(showImg,showImg,1,0,CV_MINMAX);
	imshow("show",showImg);
	waitKey();
	return label;
}

int main()
{
	Mat img=imread(filename,1);
	GaussianBlur(img,img,Size(3,3),0);
	img.convertTo(img,CV_32FC3);
	Mat pixId=clustering(img);
}

学习OpenCV——Kmean(C++)_第1张图片

你可能感兴趣的:(C++,Random,Class,each,initialization,stdstring)