淘先锋技术网

首页 1 2 3 4 5 6 7

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

kmeans

C++:  double kmeans (InputArray data, int  K, InputOutputArray  bestLabels, TermCriteria criteria, int  attempts, int  flags, OutputArray centers=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: 测试初始中心是否最优

                          

 

上代码:

[cpp]  view plain  copy
 
 print?
  1.   
[cpp]  view plain  copy
 
 print?
  1. #include <string>  
  2. #include <iostream>  
  3. #include <math.h>  
  4. #include <vector>  
  5. #include <map>  
  6.   
  7. #include "opencv/cv.h"  
  8. #include "opencv/highgui.h"  
  9. #include "opencv/cxcore.h"  
  10.   
  11. #define ClusterNum (6)  
  12.   
  13. using namespace cv;  
  14. using namespace std;  
  15.   
  16. string filename="D:/demo1.jpg";  
  17.   
  18. Mat clustering(Mat src)  
  19. {  
  20.     int row = src.rows;  
  21.     int col = src.cols;  
  22.     unsigned long int size = row*col;  
  23.   
  24.     Mat clusters(size, 1, CV_32SC1);    //clustering Mat, save class label at every location;  
  25.   
  26.     //convert src Mat to sample srcPoint.  
  27.     Mat srcPoint(size, 1, CV_32FC3);      
  28.   
  29.     Vec3f* srcPoint_p = (Vec3f*)srcPoint.data;//  
  30.     Vec3f* src_p = (Vec3f*)src.data;  
  31.     unsigned long int i;  
  32.   
  33.     for(i = 0;i < size; i++)  
  34.     {  
  35.         *srcPoint_p = *src_p;  
  36.         srcPoint_p++;  
  37.         src_p++;  
  38.     }  
  39.     Mat center(ClusterNum,1,CV_32FC3);  
  40.     double compactness;//compactness to measure the clustering center dist sum by different flag  
  41.     compactness = kmeans(srcPoint, ClusterNum, clusters,  
  42.         cvTermCriteria (CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 0.1),ClusterNum,  
  43.         KMEANS_PP_CENTERS , center);  
  44.   
  45.     cout<<"center row:"<<center.rows<<" col:"<<center.cols<<endl;  
  46.     for (int y = 0; y < center.rows; y++)   
  47.     {  
  48.         Vec3f* imgData = center.ptr<Vec3f>(y);  
  49.         for (int x = 0; x < center.cols; x++)  
  50.         {  
  51.             cout<<imgData[x].val[0]<<" "<<imgData[x].val[1]<<" "<<imgData[x].val[2]<<endl;  
  52.         }  
  53.         cout<<endl;  
  54.     }  
  55.   
  56.   
  57.     double minH,maxH;  
  58.     minMaxLoc(clusters, &minH, &maxH);          //remember must use "&"  
  59.     cout<<"H-channel min:"<<minH<<" max:"<<maxH<<endl;  
  60.   
  61.     int* clusters_p = (int*)clusters.data;  
  62.     //show label mat  
  63.     Mat label(src.size(), CV_32SC1);  
  64.     int* label_p = (int*)label.data;  
  65.     //assign the clusters to Mat label  
  66.     for(i = 0;i < size; i++)  
  67.     {  
  68.         *label_p = *clusters_p;  
  69.         label_p++;  
  70.         clusters_p++;  
  71.     }  
  72.   
  73.     Mat label_show;  
  74.     label.convertTo(label_show,CV_8UC1);  
  75.     normalize(label_show,label_show,255,0,CV_MINMAX);  
  76.     imshow("label",label_show);  
  77.   
  78.   
  79.   
  80.     map<int,int> count;       //map<id,num>  
  81.     map<int,Vec3f> avg;       //map<id,color>  
  82.   
  83.     //compute average color value of one label  
  84.     for (int y = 0; y < row; y++)   
  85.     {  
  86.         const Vec3f* imgData = src.ptr<Vec3f>(y);  
  87.         int* idx = label.ptr<int>(y);  
  88.         for (int x = 0; x < col; x++)  
  89.         {  
  90.   
  91.             avg[idx[x]] += imgData[x];  
  92.             count[idx[x]] ++;  
  93.         }  
  94.     }  
  95.     //output the average value (clustering center)  
  96.     //计算所得的聚类中心与kmean函数中center的第一列一致,  
  97.     //以后可以省去后面这些繁复的计算,直接利用center,  
  98.     //但是仍然不理解center的除第一列以外的其他列所代表的意思  
  99.     for (i = 0; i < ClusterNum; i++)  
  100.     {  
  101.         avg[i] /= count[i];  
  102.         if (avg[i].val[0]>0&&avg[i].val[1]>0&&avg[i].val[2]>0)  
  103.         {  
  104.             cout<<i<<": "<<avg[i].val[0]<<" "<<avg[i].val[1]<<" "<<avg[i].val[2]<<" count:"<<count[i]<<endl;  
  105.   
  106.         }  
  107.     }  
  108.     //show the clustering img;  
  109.     Mat showImg(src.size(),CV_32FC3);  
  110.     for (int y = 0; y < row; y++)   
  111.     {  
  112.         Vec3f* imgData = showImg.ptr<Vec3f>(y);  
  113.         int* idx = label.ptr<int>(y);  
  114.         for (int x = 0; x < col; x++)  
  115.         {  
  116.             int id = idx[x];  
  117.             imgData[x].val[0] = avg[id].val[0];  
  118.             imgData[x].val[1] = avg[id].val[1];  
  119.             imgData[x].val[2] = avg[id].val[2];  
  120.         }  
  121.     }  
  122.     normalize(showImg,showImg,1,0,CV_MINMAX);  
  123.     imshow("show",showImg);  
  124.     waitKey();  
  125.     return label;  
  126. }  
  127.   
  128. int main()  
  129. {  
  130.     Mat img=imread(filename,1);  
  131.     GaussianBlur(img,img,Size(3,3),0);  
  132.     img.convertTo(img,CV_32FC3);  
  133.     Mat pixId=clustering(img);  
  134. }  

 
 
 
from: http://blog.csdn.net/yangtrees/article/details/7971405