学习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: 测试初始中心是否最优

上代码:

[cpp] view plain copy

print?

[cpp] view plain copy

print?

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

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

时间: 2024-11-06 03:37:50

学习OpenCV——Kmean(C++)的相关文章

【从零学习openCV】IOS7人脸识别实战

前言 接着上篇<IOS7下的人脸检測>,我们顺藤摸瓜的学习怎样在IOS7下用openCV的进行人脸识别,实际上非常easy,因为人脸检測部分已经完毕,剩下的无非调用openCV的方法对採集到的人脸样本进行训练,终于得到一个能够预測人脸的模型.可是当中的原理可谓是博大精深,因为快临最近末考试了,没时间去琢磨当中详细的细节,这次就先写个大概的demo,下次更新文章就得到6月20号之后了. 原理: 从OpenCV2.4之后,openCV增加了新的类FaceRecognizer,我们能够使用它便捷地进

学习Opencv 2.4.9 (一)---Opencv + vs2012环境配置

作者:咕唧咕唧liukun321 来自:http://blog.csdn.net/liukun321 首先获得最新的Opencv 2.4.9源码:opencv源码下载 一.Opencv环境变量配置 1.将源码安装到制定目录: 2.为Opencv 添加环境变量:计算机-->属性 点击高级系统设置 3.出来系统属性对话框后,点击环境变量. 4.弹出如下对话框:选中PATH 单击新建 5.点击新建添加环境变量 6.将opencv2.4.9变量包含到PATH中去 二.然后再看VS2012 的配置. 1.

《学习opencv》笔记——矩阵和图像操作——cvGEMM,cvGetCol,cvGetCols and cvGetDiag

矩阵和图像的操作 (1)cvGEMM函数 其结构 double cvGEMM(//矩阵的广义乘法运算 const CvArr* src1,//乘数矩阵 const CvArr* src2,//乘数矩阵 double alpha,//1号矩阵系数 const CvArr* src3,//加权矩阵 double beta,//2号矩阵系数 CvArr* dst,//结果矩阵 int tABC = 0//变换标记 ); tABC变换标记及其对应的含义 CV_GEMM_A_T 转置 src1 CV_GE

学习OpenCV的学习笔记系列(三)显示图片及视频

OpenCV是计算机视觉库,那么处理的对象无非两个:"图片"及"视频"(其实视频也是被解压成单帧图像来处理的,总的来说,还是处理图像). 那么要想学习OpenCV,第一步必须知道OpenCV是怎么打开"图像"及"视频"文件然后显示的. 如果要想实现这些功能,其实很简单,步骤如下: 1. 新建工程 打开VS2010,新建一个项目,选择"Win32控制台应用程序"(使用控制台可以省掉很多麻烦),取名"

学习OpenCV研究报告指出系列(二)源代码被编译并配有实例project

下载并安装CMake3.0.1 要自己编译OpenCV2.4.9的源代码.首先.必须下载编译工具,使用的比較多的编译工具是CMake. 以下摘录一段关于CMake的介绍: CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描写叙述全部平台的安装(编译过程).他可以输出各种各样的makefile或者project文件,能測试编译器所支持的C 特性,类似UNIX下的automake.仅仅是 CMake 的组态档取名为 CmakeLists.txt.Cmake 并不直接建构出终于的软件,而是

学习OpenCV的学习笔记系列之-- 环境配置

要想学好OpenCV,首先当然要知道怎么配置环境了.以本人的配置环境为例,步骤如下. 第一步 下载及解压OpenCV源码 虽然很多第三方网站及一些学习论坛会提供OpenCV的源码下载,但是还是推荐到官网进行下载,这样可以避免很多麻烦!(病毒?木马?你懂得!) 官网的下载地址如下: http://opencv.org/downloads.html 在此地址的界面上可以找到最新版本的OpenCV源码.我使用的是2014-04-25更新的2.4.9版本(目前最新),根据自己的系统选择对应的源码版本.

《学习opencv》笔记——矩阵和图像操作——cvDet,cvDit,cvDotProduct,cvEigenVV and cvFlip

矩阵和图像的操作 (1)cvDet函数 其结构 double cvDet(//计算矩阵的行列式 const CvArr* mat ); 实例代码 #include <cv.h> #include <highgui.h> #include <stdio.h> #include <iostream> using namespace std; int main() { double va[] = {1,0,0,0,2,0,0,0,3}; CvMat Va=cvMa

学习OpenCV的学习笔记系列之-- 环境配置2

要想学好OpenCV,首先当然要知道怎么配置环境了.以本人的配置环境为例,步骤如下. 第一步 下载及解压OpenCV源码 虽然很多第三方网站及一些学习论坛会提供OpenCV的源码下载,但是还是推荐到官网进行下载,这样可以避免很多麻烦!(病毒?木马?你懂得!) 官网的下载地址如下: http://opencv.org/downloads.html 在此地址的界面上可以找到最新版本的OpenCV源码.我使用的是2014-04-25更新的2.4.9版本(目前最新),根据自己的系统选择对应的源码版本.

《学习opencv》笔记——矩阵和图像操作——cvSetIdentity,cvSolve,cvSplit,cvSub,cvSubS and cvSubRS

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump