Python下opencv使用笔记(十二)(k均值算法之图像分割)

k均值(kmeans)聚类是一种最为简单的聚类方法,直接根据数据点之间的距离(欧氏距离,几何距离等等)来划分数据是属于哪一类的,当所有数据点所属的类别不在变化的时候,聚类也就完成了。详细原理可索引下面一个博客:

聚类分析笔记-K均值matlab算法(一)

关于kmeans再谈几点认识:

  1. 重要的一点:聚类数目的问题。有的聚类、分类问题已经限制好了要聚类成几类,也就是聚类数目一定,那么这种聚类通常简单些,直接规定聚类数就好了。而有的聚类问题不知道分成几类才好,这个时候怎么办?那么就需要找到一种评价指标去评价聚类成多少类是最好的。比如说当聚类完了以后,可以计算一下类间的中心点的距离以及类内所有数据之间的距离和等等,作为判断标准,像DBI分类评价指标就是建立在这种基础上的。还有一种分类:减聚类分类,这也是在不知道分类数的时候进行的分类。
  2. 关于初始聚类中心的确定。Kmeans分类其实是具有收敛性的,所以初始聚类中心对其影响并不是很大,只要开始不相同就可以。因为在每次迭代完成以后,新的聚类中心是根据新划分类的所有点取平均而来的,所以不再受制于初始聚类中心。只是说聚类中心会影响迭代的次数,以当前计算机的速度,这点影响带来的耗时是可以不计的。
  3. 关于迭代终止条件。迭代终止条件可以有很多种,但是核心就是如何判定分类基本上已经收敛了,或者非常接近最优解,收敛不动了。一般情况下,可以设定迭代次数作为终止条件,还可以设定所有聚类中心在上下两次迭代过程中不发生变化时认为收敛,或者前后两次迭代的类中心之间的距离差小于某一个小的常数时认为收敛

关于opencv下的kmean算法,函数为cv2.kmeans()
函数的格式为:kmeans(data, K, bestLabels, criteria, attempts, flags)
(1)data: 分类数据,最好是np.float32的数据,每个特征放一列。之所以是np.float32原因是这种数据类型运算速度快,同样的数据下如果是uint型数据将会慢死你。
(2) K: 分类数,opencv2的kmeans分类是需要已知分类数的。
(3) bestLabels:预设的分类标签:没有的话 None
(4) criteria:迭代停止的模式选择,这是一个含有三个元素的元组型数。格式为(type,max_iter,epsilon)
其中,type又有两种选择:
—–cv2.TERM_CRITERIA_EPS :精确度(误差)满足epsilon停止。
—- cv2.TERM_CRITERIA_MAX_ITER:迭代次数超过max_iter停止。
—-cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER,两者合体,任意一个满足结束。
(5)attempts:重复试验kmeans算法次数,将会返回最好的一次结果
(6)flags:初始类中心选择,两种方法
cv2.KMEANS_PP_CENTERS ; cv2.KMEANS_RANDOM_CENTERS

下面使用这个函数对灰度图像进行分类。首先需要明白的一点是输入数据变换到一维。因为我们是对整个图像进行聚类,所以他们的灰度值都属于一个特征(维度)内的,而图像属于二维的,所以不能直接当data输入进去,需要将图像转化为一个长条或者长链的一维数据。我们说data结束数据,每一个特征放一列,灰度图像聚类的灰度值就是一个特征。若果说是彩色图像聚类,那么这个时候需要分别把RGB三个通道转化为一维才行。最后把分类结果以图像的形式显示出来的时候,需要把长条或者长链的标签再变回来才行。详细代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('woman.jpg',0)#image read be 'gray'
plt.subplot(121),plt.imshow(img,'gray'),plt.title('original')
plt.xticks([]),plt.yticks([])

#change img(2D) to 1D
img1 = img.reshape((img.shape[0]*img.shape[1],1))
img1 = np.float32(img1)

#define criteria = (type,max_iter,epsilon)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER,10,1.0)

#set flags: hou to choose the initial center
#---cv2.KMEANS_PP_CENTERS ; cv2.KMEANS_RANDOM_CENTERS
flags = cv2.KMEANS_RANDOM_CENTERS
# apply kmenas
compactness,labels,centers = cv2.kmeans(img1,4,None,criteria,10,flags)

img2 = labels.reshape((img.shape[0],img.shape[1]))
plt.subplot(122),plt.imshow(img2,'gray'),plt.title('kmeans')
plt.xticks([]),plt.yticks([])

Python下opencv使用笔记(十二)(k均值算法之图像分割)_第1张图片

这就是设置分成4类的结果。

你可能感兴趣的:(opencv,图像处理,python,模式识别&机器学习,opencv+python)