使用C++、opencv中的Kmeans进行图像分割
K-means算法的原理
K-means算法是基于距离相似性的聚类算法,通过比较样本之间的相似性,将形式的样本划分到同一个类别中,K-Means算法的基本过程为:
- 初始化常数 ,随机初始化k个聚类中心。
- 重复计算以下过程,直到聚类中心不再改变:
计算每个样本与每个聚类中心之间的相似度,将样本划分到最相似的类别中;
计算划分到每个类别中的所有样本特征的均值,并将该均值作为每个类新的聚类中心;
在K-Means算法中,需要随机初始化k个聚类中心,而K-Means算法对初始聚类中心的选取较为敏感,若选择的聚类中心不好,则得到的聚类结果会非常差,因此,对K-Means算法提出了很多的改进的方法,如K-Means++算法,在K-Means++算法中,希望初始化的k个聚类中心之间的距离尽可能的大,其具体过程为:
- 在数据集中随机选择一个样本点作为第一个初始化的聚类中心
- 选择出其余的聚类中心:
计算样本中的每一个样本点与已经初始化的聚类中心之间的距离,并选择其中最短的距离
以概率选择距离最大的样本作为新的聚类中心,重复上述过程,直到 个聚类中心都被确定
- 对k个初始化的聚类中心,利用K-Means算法计算最终的聚类中心。
更多关于 K-Means算法的原理可查看:https://www.cnblogs.com/pinard/p/6164214.html
https://blog.csdn.net/loveliuzz/article/details/78783773
opencv中关于Kmeans的API:
double kmeans(InputArray data, int K, InputOutputArray bestLabels, TermCriteria criteria, int attempts, int flags, OutputArray centers=noArray() )
data: 需要自动聚类的数据,一般是一个Mat。浮点型的矩阵,每行为一个样本。
k: 取成几类,比较关键的一个参数。
bestLabels: 返回的类别标记,整型数字。
criteria: 算法结束的标准,获取期望精度的迭代最大次数
attempts: 判断某个样本为某个类的最少聚类次数,比如值为3时,则某个样本聚类3次都为同一个类,则确定下来。
flags: 确定簇心的计算方式。有三个值可选:KMEANS_RANDOM_CENTERS 表示随机初始化簇心。KMEANS_PP_CENTERS 表示用kmeans++算法来初始化簇心,KMEANS_USE_INITIAL_LABELS 表示第一次聚类时用用户给定的值初始化聚类,后面几次的聚类,则自动确定簇心。
centers: 用来初始化簇心的。与前一个flags参数的选择有关。如果选择KMEANS_RANDOM_CENTERS随机初始化簇心,则这个参数可省略。
使用聚类的方法分割图像,即将图像的像素点值(通常用彩色图像,像素点值为一个三元数组(b,g,r))作为聚类的元素,从而将图像中所有的点分为n类,达到分割的效果。这里只是展示代码效果,实际上可以根据需要,将其他颜色参数(如H、S、I、L、a、b等)、颜色参数的组合(NRI、NGI、NBI等)作为分类的数据点传入训练器,这样可能会对复杂的分割有帮助。
代码如下:
#include "stdafx.h"
#include
#include
#include
#include
#include
源图:
标签图(分类后的结果,代码中分为2类):
结果图: