kmeans算法主要用来实现自动聚类,是一种非监督的机器学习算法,使用非常广泛。在opencv3.0中提供了这样一个函数,直接调用就能实现自动聚类。在使用kmeans之前,必须先了解kmeans算法的2个缺点:第一是必须人为指定所聚的类的个数k;第二是如果使用欧式距离来衡量相似度的话,可能会得到错误的结果,因为没有考虑到属性的重要性和相关性。为了减少这种错误,在使用kmeans距离时,一定要使样本的每一维数据归一化,不然的话由于样本的属性范围不同会导致错误的结果。
kmeans
double cv::kmeans(
InputArray data, //需要自动聚类的数据,一般是一个Mat。浮点型的矩阵,每行为一个样本。
int K, //要拆分集的群集数
InputOutputArray bestLabels, //输入/输出整数数组,用于存储每个样本的群集索引
TermCriteria criteria, //算法终止标准,即最大迭代次数和/或所需精度。精度规定为criteria.epsilon。在某些迭代中,一旦每个簇中心的移动小于criteria.epsilon,算法就会停止。
int attempts, //用于指定使用不同初始标签执行算法的次数的标志。算法返回产生最佳紧凑性的标签(参见最后一个函数参数)。即判断某个样本为某个类的最少聚类次数,比如值为3时,则某个样本聚类3次都为同一个类,则确定下来
int flags, //cv::KmeansFlags的标志
有三个值可选:KMEANS_RANDOM_CENTERS 表示随机初始化簇心。KMEANS_PP_CENTERS 表示用kmeans++算法来初始化簇心(没用过),KMEANS_USE_INITIAL_LABELS 表示第一次聚类时用用户给定的值初始化聚类,后面几次的聚类,则自动确定簇心。
OutputArray centers = noArray() //集群中心的输出矩阵,每个集群中心一行。如果选择
KMEANS_RANDOM_CENTERS随机初始化簇心,则这个参数可省略。
)
参数说明:
参数名称 | 解释 |
data | 表示输入的数据集合,可以一维或者多维数据,类型是Mat类型,比如Mat points(count, 2, CV_32F)表示数据集合是二维,浮点数数据集 |
K | 表示分类的数目,最常见的是K=2表示二分类 |
bestLabels | 表示计算之后各个数据点的最终的分类索引,是一个INT类型的Mat对象 |
criteria | 表示算法终止的条件,达到最大循环数目或者指定的精度阈值算法就停止继续分类迭代计算 |
attempts | 表示为了获得最佳的分类效果,算法要不同的初始分类尝试次数 |
flags | 表示表示选择初始中心点选择方法用哪一种KMEANSRANDOMCENTERS 表示随机选择中心点。KMEANSPPCENTERS 基于中心化算法选择。KMEANSUSEINITIAL_LABELS第一次分类中心点用输入的中心点 |
centers | 表示输出的每个分类的中心点数据 |
Mat src = imread("test.png", IMREAD_COLOR);
imshow("【原图】", src);
Mat q_matsrcClone = src.clone();
Mat q_matdata/*(Size(3, q_matsrcClone.rows), CV_8UC1, Scalar::all(0))*/;
for (int row = 0; row < q_matsrcClone.rows; ++row)
{
for (int col = 0; col < q_matsrcClone.cols; ++col)
{
//Vec3b point = q_matsrcClone.at<Vec3b>(row, col);
Vec3b *ptr = q_matsrcClone.ptr<Vec3b>(row, col);
Mat q_mattemp = (Mat_<float>(1, 3) << ptr->val[0], ptr->val[1], ptr->val[2]);
q_matdata.push_back(q_mattemp);
//Vec3b *ptr = q_matsrcClone.ptr<Vec3b>(row, col);
//q_matdata = (Mat_<uchar>(row, 3) << ptr->val[0], ptr->val[1], ptr->val[2]); //error
//q_matdata = (Mat_<uchar>(1, 3) << ptr->val[0], ptr->val[1], ptr->val[2]);
//q_matdata.row(row).setTo(Scalar(ptr->val[0], ptr->val[1], ptr->val[2]));
}
}
//浏览图片,确定大概 K = 5
Mat q_matlabels;
TermCriteria q_Scriteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0);
kmeans(q_matdata, 5, q_matlabels, q_Scriteria, 3, KMEANS_RANDOM_CENTERS);
int i = 0;
//显示聚类结果,不同的类别用不同的颜色显示
Vec3b q_colorTab[] =
{
Vec3b(0, 0, 255),
Vec3b(0, 255, 0),
Vec3b(255, 100, 100),
Vec3b(255, 0, 255),
Vec3b(0, 255, 255)
};
for (int row = 0; row < q_matsrcClone.rows; ++row)
{
for (int col = 0; col < q_matsrcClone.cols; ++col)
{
int* q_clusterIdPtr = q_matlabels.ptr<int>(i++);
//Vec3b *ptr = q_matsrcClone.ptr<Vec3b>(row, col);
*q_matsrcClone.ptr<Vec3b>(row, col) = q_colorTab[*q_clusterIdPtr];
//n++;
}
}
imshow("q_matsrcClone", q_matsrcClone);