原博文链接:http://www.cnblogs.com/smyb000/archive/2012/08/28/k-means_cluster_via_vlfeat.html

                                                                    ~~~~多谢原作者的分享,代码部分稍有改动,以适应系统环境~~~
                                                                   环境:win 7 64专业版,VS2013,opencv2.4.9,Vlfeat 0.9.20.
                                                    配置:可参考我之前的博文http://blog.csdn.net/lilai619/article/details/50538303

摘要

本文将介绍如何使用VLFeat开源库来进行K-means聚类,关于K-means的介绍可以参考这里。

什么是VLFeat

用VLFeat官方主页的话来说,VLFeat 是一个实现了视觉领域诸多算法的开源库,其包括SIFTMSER,  k-meanshierarchical k-meansagglomerative information bottleneck, quick shift 等等。底层代码用C语言实现,并提供了MATLAB接口。支持WindowsMac OS X, 和 Linux。最新版本为VLFeat 0.9.20

和OpenCV相比,VLFeat是一个轻量级的库,主要实现了在特征提取和聚类方面的高效算法, 可以用在图像检索和物体识别领域中。

Integer K-means (IKM) 介绍

接下来将介绍如何用VLFeat库来进行k-means聚类。

VLFeat 提供了k-means 聚类和分层k-means聚类的轻量级的实现。需要注意的是,IKmeans聚类数据的类型是unsigned char型。虽然这看上去有局限性,但对于图像的特征聚类,算法有很高的准确性,因为在高维空间中(例如SIFT特征,128维),UCHAR型已经足够。C语言的Integer K-means的接口文档请看这里。

Integer K-means (IKM) 实现了整型数据的 K-means 聚类 (或者叫矢量量化)。在图像检索、识别领域,经常会用到Bag-of-words(BOW)模型,该模型对训练集图像提取特征并进行聚类,得到固定数量的代表性特征集(dictionary), 将测试集中提取出来的特征进行量化,用之前得到代表性特征集中的特征(word)来表示,这样每幅图像就可以表示成bag-of-words。该功能可以用VLFeat库轻松实现。

如何使用接口?

用VLFeat进行K-means 聚类,需要包含 ikmeans.h 头文件,其声明了如下接口:

数据结构

struct   VlIKMFilt

量化器,k-means聚类的核心数据结构。聚类相关的任何函数都与此数据结构有关。

枚举类型

enum  VlIKMAlgorithms { VL_IKM_LLOYD, VL_IKM_ELKAN }

VLFeat 实现了两种聚类算法,在进行训练时作为参数传入给vl_ikm_train 函数。

函数

VlIKMFilt  * vl_ikm_new (int method)

创建量化器,传入参数为VL_IKM_LLOYD或者 VL_IKM_ELKAN

void  vl_ikm_delete (VlIKMFilt *f)

删除量化器

void vl_ikm_init (VlIKMFilt *f, vl_ikm_acc const *centers, int M, int K)

指定聚类的center 对量化器初始化,M为数据的维数,K为聚类数

void vl_ikm_init_rand (VlIKMFilt *f, int M, int K)

随机生成center,并进行初始化,M为数据的维数,K为聚类数

void vl_ikm_init_rand_data (VlIKMFilt *f, vl_uint8 const *data, int M, int N, int K)

在数据中随机指定center,对量化器进行初始化,M为维数,N为数据数,K为聚类数

int vl_ikm_train (VlIKMFilt *f, vl_uint8 const *data, int N)

对输入数据进行训练, data为数据, N为数据数目。

void vl_ikm_push (VlIKMFilt *f, vl_uint *asgn, vl_uint8 const *data, int N)

将新数据量化到聚类中心,得到每个数据的标记。 asgn为数据的标记数组, data为输入数据, N为数据数目。

vl_uint vl_ikm_push_one (vl_ikm_acc const *centers, vl_uint8 const *data, int M, int K)

对一个数据进行量化

还有一些存取函数下文将省略,可以查询文档查看详情。

IKM使用步骤

step 1. 创建量化器

用 vl_ikm_new() 函数创建一个IKM 量化器(聚类器)。

step 2. 初始化 IKM量化器

用 vl_ikm_init() 或者其它接口(本文用vl_ikm_init_rand函数)。

step 3. 用 vl_ikm_train() 训练量化器。

step 4. 用vl_ikm_push() 函数或者 vl_ikm_push_one() 对新的特征进行量化(如只需要聚类,可以在这一步重复使用step 3. 的训练数据)。

开始聚类吧

准备工作就绪,开始聚类吧!

我们将随机产生值为[0,255)的2维数据点来进行k-means聚类,这样可以很直观方便地在图像中画出来看到聚类结果。

在这里用OpenCV的函数来显示二维数据点以及分类结果。

首先包含必须的头文件 ikmeans.h。

extern "C" {
#include "ikmeans.h"
}

用OpenCV建立矩阵来显示随机生成的数据以及聚类后的结果。

int row = 255;
int col = 255;
Mat show = Mat::zeros(row, col, CV_8UC3);
Mat show2 = show.clone();

创建随机训练数据,用200组2维数据进行训练。并在图像中绘制数据点。

int data_num = 200;
int data_dim = 2;
vl_uint8 *data = new vl_uint8[data_num * data_dim];for( int i=0; i<data_num; ++i)
{vl_uint8 x = data[i*data_dim] = rand()% col;vl_uint8 y = data[i*data_dim+1] = rand()% row;circle(show,Point(x,y),2,Scalar(255,255,255));
}

如下图所示,生成了200个点的数据。

图1.随机生成的数据点

接下来的几行代码将创建量化器,训练,并得到量化结果,在这里,用训练数据作为新数据传给量化器,这样就可以得到训练数据的聚类结果,聚类数目为K=3。

VlIKMFilt *kmeans = vl_ikm_new(VL_IKM_ELKAN);
vl_uint K = 3;
vl_ikm_init_rand(kmeans, data_dim, K);
vl_ikm_train(kmeans, data, data_num);
vl_uint * label = new vl_uint[data_num];
vl_ikm_push(kmeans, label, data, data_num);

在上面的代码中,label数组存放的就是量化结果,量化的序号为0,1,2...,K-1。

最后,画图,显示结果。

    for( int i=0;i<data_num; ++i){vl_uint8 x = data[i*data_dim];vl_uint8 y = data[i*data_dim+1];switch(label[i]){case 0:circle(show2,Point(x,y),2,Scalar(255,0,0));break;case 1:circle(show2,Point(x,y),2,Scalar(0,255,0));break;case 2:circle(show2,Point(x,y),2,Scalar(0,0,255));break;}}

结果如下图所示:

图2.聚类(量化)结果

最后别忘了删除聚类器,以及清空数组。

vl_ikm_delete(kmeans);
delete []label;
label = NULL;
delete []data;
data = NULL;

整个程序的源代码如下:

//提示无法启东此程序,因为计算机中丢失vl.dll。
//解决策略:将\vlfeat\bin\win32路径下的vl.dll拷贝到项目生成的debug文件夹再编译就OK了.
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
extern "C" {
#include "vl/ikmeans.h"
}
using namespace std;
using namespace cv;int main()
{
    /*initialize data point*/
    int row = 255;
    int col = 255;
    Mat show = Mat::zeros(row, col, CV_8UC3);
    Mat show2 = show.clone();
    int data_num = 200;
    int data_dim = 2;
    vl_uint8 *data = new vl_uint8[data_num * data_dim];//new 表示动态申请开辟空间,所以左值必须为指针类型 for (int i = 0; i<data_num; ++i)
    {
        vl_uint8 x = data[i*data_dim] = rand() % col;
        vl_uint8 y = data[i*data_dim + 1] = rand() % row;
        circle(show, Point(x, y), 2, Scalar(255, 255, 255));
    }   //初始化量化器
    VlIKMFilt *kmeans = vl_ikm_new(VL_IKM_ELKAN);
    //设置聚类中心
    vl_uint K = 3;
    //随机初始化聚类中心
    vl_ikm_init_rand(kmeans, data_dim, K);
    //训练
    vl_ikm_train(kmeans, data, data_num);
    //label中存放数据所属的类别信息
    vl_uint *label = new vl_uint[data_num];
    for (int i = 0; i<data_num; ++i)
    {
        vl_uint8 x = data[i*data_dim];
        vl_uint8 y = data[i*data_dim + 1];
        switch (label[i])
        {
        case 0:
            circle(show2, Point(x, y), 2, Scalar(255, 0, 0));
            break;
        case 1:
            circle(show2, Point(x, y), 2, Scalar(0, 255, 0));
            break;
        case 2:
            circle(show2, Point(x, y), 2, Scalar(0, 0, 255));
            break;
        }
    }   imwrite("show.jpg", show);
    imwrite("show2.jpg", show2);
    Mat img1 = imread("show.jpg");
    Mat img2 = imread("show2.jpg");
    namedWindow("原图");
    imshow("原图", img1);
    namedWindow("聚类效果图");
    imshow("聚类效果图", img2);
    vl_ikm_delete(kmeans);  delete[]label;
    label = NULL;
    delete[]data;
    data = NULL;   waitKey(6000);
    return 0;
}

用VLFeat库进行k-means聚类(C++ 实现)相关推荐

  1. OpenCV的k - means聚类 -对图片进行颜色量化

    OpenCV的k - means聚类 目标 学习使用cv2.kmeans()数据聚类函数OpenCV 理解参数 输入参数 样品:它应该的np.float32数据类型,每个特性应该被放在一个单独的列. ...

  2. OpenCV官方文档 理解k - means聚类

    理解k - means聚类 目标 在这一章中,我们将了解k - means聚类的概念,它是如何工作等. 理论 我们将这个处理是常用的一个例子. t恤尺寸问题 考虑一个公司要发布一个新模型的t恤. 显然 ...

  3. k means聚类算法_K-Means 聚类算法 20210108

    说到聚类,应先理解聚类和分类的区别 聚类和分类最大的不同在于:分类的目标是事先已知的,而聚类则不一样,聚类事先不知道目标变量是什么,类别没有像分类那样被预先定义出来. K-Means 聚类算法有很多种 ...

  4. python机器学习库sklearn——k均值聚类

    全栈工程师开发手册 (作者:栾鹏) python数据挖掘系列教程 k均值聚类的相关的知识内容可以参考 http://blog.csdn.net/luanpeng825485697/article/de ...

  5. k means聚类算法_一文读懂K-means聚类算法

    1.引言 什么是聚类?我们通常说,机器学习任务可以分为两类,一类是监督学习,一类是无监督学习.监督学习:训练集有明确标签,监督学习就是寻找问题(又称输入.特征.自变量)与标签(又称输出.目标.因变量) ...

  6. 机器学习(十四):K均值聚类(kmeans)

    k均值聚类方法是一种无监督机器学习技术,用于识别数据集中的数据对象集群.有许多不同类型的聚类方法,但k -means是最古老和最平易近人的方法之一.这些特性使得在 Python 中实现k -means ...

  7. k均值聚类算法(K Means)及其实战案例

    算法说明 K均值聚类算法其实就是根据距离来看属性,近朱者赤近墨者黑.其中K表示要聚类的数量,就是说样本要被划分成几个类别.而均值则是因为需要求得每个类别的中心点,比如一维样本的中心点一般就是求这些样本 ...

  8. k均值聚类算法考试例题_k means聚类算法实例

    所谓聚类问题,就是给定一个元素集合D,其中每个元素具有n个可观察属性,使用某种算法将D划分成k个子集,要求每个子集内部的元素之间相异度尽可能低,而不同子集的元素相异度尽可能高.其中每个子集叫做一个簇. ...

  9. k均值聚类算法python_K均值和其他聚类算法:Python快速入门

    k均值聚类算法python This post was originally published here 这篇文章最初发表在这里 Clustering is the grouping of obje ...

最新文章

  1. [短文速读] 重载有暗坑,JVM是如何执行方法的
  2. 互联网产品接入支付功能如何测试?
  3. spring计算方圆300km内其它城市(附完整代码)
  4. 在c语言中函数的定义变量的值为,变量定义(C语言中变量的声明和定义)
  5. 数据结构之并查集:路径压缩继续优化并查集——20
  6. mysql外部排序_深入浅出MySQL优先队列(你一定会踩到的order by limit 问题)
  7. 建立在Windows XP欢迎屏幕中隐藏的用户
  8. 斗地主AI算法——第二章の数据结构
  9. 使用Docker Compose管理多个容器
  10. Android更改桌面应用程序launcher的两种方式
  11. java词频统计——web版支持
  12. exosip鉴权及使用
  13. Redis集群启动时发生如下错误:Node hadoop103:7002 replied with error: ERR Invalid node address specified: hadoop1
  14. oracle之SQL的基本函数
  15. javaee之spring3
  16. 腾讯 爱奇艺服务器(网址)无法访问(打不开,没有网络)
  17. LAMP环境部署及搭建网校系统
  18. 【心情分享】自己心中的程序员和别人眼里的程序员
  19. Javaweb8==通过tomcat访问到一段代码并执行,同时读取前端数据和从后端给前端返回数据。通过继承javaEE的HttpServlet类。实现登录注册功能和前端界面。
  20. unity接入声网音频sdk

热门文章

  1. YubiKey USB安全密钥也出现臭虫可免费换新
  2. 8647服务器装系统,机柜系统资料的.doc
  3. 解析创新教育体系中的创客教育
  4. 如何删除图片数据中的重复数据
  5. 【进程管理】进程 P1、P2 、P3、P4 和 P5 的前趋图如下所示:
  6. i.MX6ULL终结者Linux 电容触摸屏实验硬件原理图
  7. Android Animation之ScaleAnimation用法详解
  8. Redis和数据库的读写操作分析
  9. 壳聚糖-甲氨蝶呤|Chitosan-MTX|甲氨蝶呤-PEG-壳聚糖
  10. jsp+ssh+mysql实现的Java web学生考勤管理系统源码附带视频指导运行教程