K均值用法

来源:互联网 发布:查九牧卫浴型号软件 编辑:程序博客网 时间:2024/06/05 07:23

C++: double kmeans(InputArray data, int K, InputOutputArray bestLabels, TermCriteria criteria, int attempts, int flags, OutputArray centers=noArray() )
参数说明:
data:
聚类的数据,是N维的数组类型,必须是浮点型。
K:
表示需要聚类的类别数
bestLabels:
聚类后的标签数组,Mat型
criteria:
迭代收敛准则
attemps:
表示尝试的次数,防止陷入局部最优
flags:
表示聚类中心的选取方式,KMEANS_RANDOM_CENTERS 随机选取,KMEANS_PP_CENTERS使用Arthur提供的算法,KMEANS_USE_INITIAL_LABELS使用初始标签
centers:
聚类后的类别中心

K均值是一个迭代算法,在opencv中采用的是Lloyd算法,也叫Voronoi迭代,算法运行包括如下:

  1. 输入数据集合和类别数K(由用户定义)。
  2. 随机分配类别中心点的位置。
  3. 将每个点放入离它最近的类别中心所在的集合。
  4. 移动类别中心到它所在集合的中心。
  5. 转到第三部,直到收敛。
#include <opencv.hpp>#include <opencv2/core.hpp>#include <opencv2/ml.hpp>void main(){#define MAX_CLUSTERS 5     cv::Scalar color_tab[MAX_CLUSTERS];    cv::Mat img = cv::Mat(500, 500, CV_8UC3 , cv::Scalar(0 , 0 , 0));    cv::RNG rng = cv::RNG(0xffffffff);    color_tab[0] = { 255 , 0 , 0 };    color_tab[1] = { 0 , 255 , 0 };    color_tab[2] = { 100 , 100 , 255 };    color_tab[3] = { 255 , 0 , 255 };    color_tab[4] = { 255 , 255 , 0 };    cv::namedWindow("clusters", 1);    for (; ;)    {        int k;        int cluster_count = (unsigned)rng() % (MAX_CLUSTERS + 1);        int i;        int sample_count = (unsigned)rng % (1000 + 1);        std::cout << "聚类数量:" << cluster_count << std::endl;        std::cout << "样本数量:" << sample_count << std::endl;        cv::Mat points = cv::Mat(sample_count, 1, CV_32FC2);        cv::Mat clusters = cv::Mat(sample_count, 1, CV_32SC1);        for (k = 0 ; k < cluster_count ; k++)        {            cv::Point2i center;            cv::Mat point_chunk;            center.x = (unsigned)(rng) % (img.cols);            center.y = (unsigned)(rng) % (img.rows);            point_chunk = points.rowRange(k * sample_count / cluster_count, k == cluster_count - 1 ? sample_count : (k + 1) * sample_count / cluster_count);            rng.fill(point_chunk, cv::RNG::NORMAL, cv::Scalar(center.x, center.y, 0.0), cv::Scalar(img.cols / 6, img.rows / 6, 0));        }        for (i = 0 ; i < sample_count/2 ; i++)        {            cv::Point2f pt1 = points.at<cv::Point2f>(rng() % sample_count);            cv::Point2f pt2 = points.at<cv::Point2f>(rng() % sample_count);            cv::Point2f temp;            CV_SWAP(pt1, pt2 , temp);        }        cv::kmeans(points, cluster_count, clusters, cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 10, 1.0) , 5 , cv::KMEANS_RANDOM_CENTERS);        for (i = 0 ; i < sample_count ; ++i)        {            cv::Point2f pt = points.at<cv::Point2f>(i);            int cluster_idx = clusters.at<int>(i);            cv::circle(img, pt, 2, color_tab[cluster_idx], 2);        }        cv::imshow("cluster", img);        cv::waitKey(0);    }}