您的位置:首页 > 编程语言 > C语言/C++

学习OpenCV——Kmean(C++)

2012-09-12 16:08 429 查看
从前也练习使用过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);
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息