cvKMeans2函数用法概述
一般情况下,我们通过C++/Matlab/Python等语言进行实现K-means算法,结合近期我刚刚学的C++,先从C++实现谈起,C++里面我们一般采用的是OpenCV库中写好的K-means函数,即cvKmeans2,首先来看函数原型:
从OpenCV manual看到的是:
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);
由于除去已经确定的参数,我们自己需要输入的为:
void cvKMeans2(
const CvArr* samples, //输入样本的浮点矩阵,每个样本一行。
int cluster_count, //所给定的聚类数目
* labels, //输出整数向量:每个样本对应的类别标识 ,注意:该变量的行数必须与samples的行数是一致的
CvTermCriteria termcrit //指定聚类的最大迭代次数和/或精度(两次迭代引起的聚类中心的移动距离)
);
一个例程如下所示:
1 #ifdef _CH_
2 #pragma package <opencv>
3 #endif
4
5 #define CV_NO_BACKWARD_COMPATIBILITY
6
7 #ifndef _EiC
8 #include "cv.h"
9 #include "highgui.h"
10 #include <stdio.h>
11 #endif
12
13 int main( int argc, char** argv )
14 {
15 #define MAX_CLUSTERS 5 //设置类别的颜色,个数(《=5)
16 CvScalar color_tab[MAX_CLUSTERS];
17 IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
18 CvRNG rng = cvRNG(-1);
19 CvPoint ipt;
20
21 color_tab[0] = CV_RGB(255,0,0);
22 color_tab[1] = CV_RGB(0,255,0);
23 color_tab[2] = CV_RGB(100,100,255);
24 color_tab[3] = CV_RGB(255,0,255);
25 color_tab[4] = CV_RGB(255,255,0);
26
27 cvNamedWindow( "clusters", 1 );
28
29 for(;;)
30 {
31 char key;
32 int k, cluster_count = cvRandInt(&rng)%MAX_CLUSTERS + 1;
33 int i, sample_count = cvRandInt(&rng)%1000 + 1;
34 CvMat* points = cvCreateMat( sample_count, 1, CV_32FC2 );//这里实际上的列数可以是很多列,并不一定仅仅是局限于这种两列(因为这里每列是一个二元数组)
35 CvMat* clusters = cvCreateMat( sample_count, 1, CV_32SC1 );
36 cluster_count = MIN(cluster_count, sample_count);
37
38 /** generate random sample from multigaussian distribution */
39 for( k = 0; k < cluster_count; k++ )
40 {
41 CvPoint center;
42 CvMat point_chunk;
43 center.x = cvRandInt(&rng)%img->width;
44 center.y = cvRandInt(&rng)%img->height;
45 cvGetRows( points, &point_chunk, k*sample_count/cluster_count,
46 k == cluster_count - 1 ? sample_count :
47 (k+1)*sample_count/cluster_count, 1 );
48
49 cvRandArr( &rng, &point_chunk, CV_RAND_NORMAL,
50 cvScalar(center.x,center.y,0,0),
51 cvScalar(img->width*0.1,img->height*0.1,0,0));
52 }
53
54 /** shuffle samples */
55 for( i = 0; i < sample_count/2; i++ )
56 {
57 CvPoint2D32f* pt1 = (CvPoint2D32f*)points->data.fl + cvRandInt(&rng)%sample_count;
58 CvPoint2D32f* pt2 = (CvPoint2D32f*)points->data.fl + cvRandInt(&rng)%sample_count;
59 CvPoint2D32f temp;
60 CV_SWAP( *pt1, *pt2, temp );
61 }
62
63 printf( "iterations=%d\n", cvKMeans2( points, cluster_count, clusters,
64 cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 1.0 ),
65 5, 0, 0, 0, 0 ));//作者备注:cvKMeans2返回值为迭代次数?用户手册里面的意思应该是返回体现各个类别与类中心的差别的 compactness量度吧
66
67 cvZero( img );
68
69 for( i = 0; i < sample_count; i++ )
70 {
71 int cluster_idx = clusters->data.i[i];
72 ipt.x = (int)points->data.fl[i*2];
73 ipt.y = (int)points->data.fl[i*2+1];
74 cvCircle( img, ipt, 2, color_tab[cluster_idx], CV_FILLED, CV_AA, 0 );
75 }
76
77 cvReleaseMat( &points );
78 cvReleaseMat( &clusters );
79
80 cvShowImage( "clusters", img );
81
82 key = (char) cvWaitKey(0);
83 if( key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
84 break;
85 }
86
87 cvDestroyWindow( "clusters" );
88 return 0;
89 }
90
91 #ifdef _EiC
92 main(1,"kmeans.c");
93 #endif
另外,关于KMeans与SIFT算子的一个结合应用,有一个很好的帖子就是参考[2]中的内容。
此处为了说明其对KMeans使用的理解,将其第四部分step2内容备份于此。
Step2——Kmeans应用
Step1里面的feature只是“预备单词”,在成为单词之前还要通过Step2生成“单词表”和Step3将“文档”中的“预备单词”找到“单词表”中最相近的“单词”替换之(并不是真正操作上的替换,只是当成“单词表”中的“单词”统计出来而已)。
在Step2中,关键操作如下:
...
CvMat *samples=cvCreateMat(featureNum, dims, CV_32FC1); //包含所有图片的所有feature信息的矩阵,featureNum个feature,每个feature为dims(128)维向量,每一维的元素类型为32位浮点数
CvMat *clusters=cvCreateMat(featureNum, 1, CV_32SC1); //每个feature所在“质心”的指针(实际上本例程中没有用到该信息)
CvMat *centers=cvCreateMat(k, dims, CV_32FC1); //“质心”信息的数组,k个“质心”每个质心都是dims(128)维向量,每一维的元素类型为32位浮点数
cvSetZero(clusters); //将矩阵初始化为0
cvSetZero(centers); //将矩阵初始化为0
while(file.ReadString(strLine))
{
...
n = import_features(CIni::CStrToChar(fileName), FEATURE_LOWE, &features); //导入feature文件,n为导入的feature个数
...
//将feature文件内所有feature信息存入samples矩阵结构内
for(int i = 0; i < n; i++)
{
for(int j = 0; j < dims; j++)
{
samples->data.fl[temp++] = features[i].descr[j];
}
}
}
cvKMeans2(samples, k, clusters,cvTermCriteria(CV_TERMCRIT_EPS,10,1.0), 3, (CvRNG *)0, KMEANS_USE_INITIAL_LABELS, centers); //Kmeans聚类
...
cvSave(CIni::CStrToChar(ini.getWordListFilePath()), centers); //保存单词表
...
其中关键函数当然是import_features(...)和cvKMeans2(...),前者是sift源码里的方法,用来导入feature文件使之成为内存数据结构,后者是Opencv里的kmeans算法之一(cvKMeans2(...)内部调用了kmeans(...))。
Reference
[1]聚类算法——K-means(下) http://www.cnblogs.com/moondark/archive/2012/03/08/2385870.html
[2]基于SIFT+Kmeans+LDA的图片分类器的实现 http://www.cnblogs.com/freedomshe/archive/2012/04/24/2468747.html
cvKMeans2函数用法概述的更多相关文章
- Oracle 中 decode 函数用法
Oracle 中 decode 函数用法 含义解释:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值) 该函数的含义如下:IF 条件=值1 THEN RETURN(翻译 ...
- memcpy函数用法
memcpy函数用法 .分类: VC++ VC++ mfc matlab 2011-12-01 19:17 14538人阅读 评论(0) 收藏 举报 null 原型:extern void *memc ...
- Python回调函数用法实例详解
本文实例讲述了Python回调函数用法.分享给大家供大家参考.具体分析如下: 一.百度百科上对回调函数的解释: 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函 ...
- php中opendir函数用法实例
这篇文章主要介绍了php中opendir函数用法,以实例形式详细讲述了opendir函数打开目录的用法及相关的注意事项,具有一定的参考借鉴价值,需要的朋友可以参考下 本文实例分析了php中opendi ...
- assert()函数用法总结
assert()函数用法总结 assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行,原型定义: #include <assert.h> ...
- C语言中qsort函数用法
C语言中qsort函数用法-示例分析 本文实例汇总介绍了C语言中qsort函数用法,包括针对各种数据类型参数的排序,非常具有实用价值非常具有实用价值. 分享给大家供大家参考.C语言中的qsort ...
- OVER(PARTITION BY)函数用法
OVER(PARTITION BY)函数介绍 开窗函数 Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个组返 ...
- qsort函数用法【转】
qsort函数用法 qsort 功 能: 使用快速排序例程进行排序 用 法: void qsort(void *base, int nelem, int width, int (*fcmp)(con ...
- Perl Sort函数用法总结和使用实例
一) sort函数用法 sort LISTsort BLOCK LISTsort SUBNAME LIST sort的用法有如上3种形式.它对LIST进行排序,并返回排序后的列表.假如忽略了SUBNA ...
随机推荐
- MongoDB 副本集的相关概念【转】
一.副本集基本概念 副本集(replica set) MongoDB的replica set是一个mongod进程实例簇,数据在这个簇中相互复制,并自动进行故障切换. MongoDB的数据库复制增加了 ...
- 请确认 <Import> 声明中的路径正确,且磁盘上存在该文件。
在网上下了个源码打开报错. 请确认 <Import> 声明中的路径正确,且磁盘上存在该文件. 一查,原来是路径错误. 解决办法:将项目文件(.csproj)用记事本打开,然后找到<I ...
- 解决Windows10下80端口被PID为4的System占用的问题
一.背景 最近由于好奇心,更新了windows10系统,感觉上手还蛮快,而且体验还不错,但是在IDEA中做开发时,使用80端口进行启动项目的时候发现端口被占用了,于是尝试解决这个问题.具体步骤如下,分 ...
- 晨跑(bzoj 1877)
Description Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个十 ...
- 图像特征提取之LBP特征
LBP(Local Binary Pattern,局部二值模式)是一种用来描述图像局部纹理特征的算子:它具有旋转不变性和灰度不变性等显著的优点.它是首先由T. Ojala, M.Pietik?inen ...
- Mysql之取消主从复制
Mysql5.7 Mysql取消主从复制很简单.只需在其要终止同步的Server上[一般是Slave]执行下面语句即可: stop slave; reset slave; 如图: .
- hdu1492(约数个数定理)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1492 这里先讲一下约数个数定理: 对于正整数x,将其质因分解为 x = pow(p1, a) * po ...
- 自己动手编译hadoop-2.5.2源码
搭建环境:Centos x 6.5 64bit (后来:我才知道原来官网上发布的就是64位的,不过这个对我来说是个学习过程,对以后进行其他平台编译的时候有帮助!) 1.安装JDK 我这里用的是64位 ...
- Chrome Crx 插件下载
扯蛋的GFW屏蔽了google域导致下载Chrome插件加载失败,本人想收集以些chrome的Crx插件,可供直接下载 XMarks - 在不同电脑不同浏览器之间同步书签 下载地址: http:/ ...
- [LeetCode] Validate Binary Search Tree (两种解法)
Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...