【Machine Learning】OpenCV中的K-means聚类

在上一篇(【Machine Learning】K-means算法及优化)中,我们介绍了K-means算法的基本原理及其优化的方向。opencv中也提供了K-means算法的接口,这里主要介绍一下如何在python+opencv的环境下,使用k-means接口(C++的接口形式相似)。

python版本的k-means算法接口,即cv2.kmeans()


输入参数

-samples: 类型必须是np.float32型,每个特征应该放置在单独的一个列中;

-nclusters(K):最终要确定的类别数;

-criteria:迭代终止的条件,3通道参数,分别是(type, max_iter, epsilon):

  • 3.a -type: 终止条件的类型,有如下3个flag: cv2.TERM_CRITERIA_EPS(精度满足epsilon时,终止迭代);cv2.TERM_CRITERIA_MAX_ITER(最大迭代次数达到后终止);cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER(二者满足其一即可终止迭代);
  • 3.b -  max_iter:最大迭代次数;
  • 3.c - epsilon:精度;

-attempts: 算法使用不同初始化标识执行的次数,改算法返回最佳集聚性的标签,该值作为输出值返回;

-flags:用于指定如何初始化聚类中心,通常有两种方式:cv2.KMEANS_PP_CENTERS(初始的K个点)和cv2.KMEANS_RANDOM_CENTERS(随机产生的K个点)。

扫描二维码关注公众号,回复: 2743034 查看本文章


输出参数

-compactness: 集聚性,指每个点到相应聚类中心点的距离平方的和;

-labels:聚类的标识序列(‘0’, ‘1’......);

-centers:聚类中心的序列。


1、一维特征的聚类

首先,使用如下代码,创建一个随机数组序列,并绘制其分布直方图:

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

x = np.random.randint(25,100,25)
y = np.random.randint(175,255,25)
z = np.hstack((x,y))
z = z.reshape((50,1))
z = np.float32(z)
plt.hist(z,256,[0,256]),plt.show()

由此,我们可以得到一个大小为50的数组‘Z’,值的范围为0-255。这里,将z转换成列向量,这样对不止一个特征的聚类会非常有帮助,值的数据类型为np.float32。直方分布图如下:

这里,调用K-means方程,首先我们要设定好criteria,这里最大迭代次数设定为10,误差设定为1.0,且终止条件指定为不管达到误差还是达到最大迭代次数,都将终止迭代。同时,指定将以上数据聚类为2类。具体代码如下:

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

# Set flags (Just to avoid line break in the code)
flags = cv2.KMEANS_RANDOM_CENTERS

# Apply KMeans
compactness,labels,centers = cv2.kmeans(z,2,None,criteria,10,flags)

这里返回了compactness, labels and centers.这里,我们得到64和210两个中心点(每次运行可能不太一样,因为数据是随机出来的)。labels的大小和输入数据的大小相同,每个数据都将根据他们所属类的中心被标记为‘0’,‘1’,‘2’ 等等。下面将根据他们的标识,将数据按类分离开:

A = z[labels==0]
B = z[labels==1]

下面将A类用红色绘制,B类用蓝色绘制,他们的中心均用黄色绘制:

# Now plot 'A' in red, 'B' in blue, 'centers' in yellow
plt.hist(A,256,[0,256],color = 'r')
plt.hist(B,256,[0,256],color = 'b')
plt.hist(centers,32,[0,256],color = 'y')
plt.show()

可得到如下结果:


2、多维特征的聚类


下面考虑二维特征的聚类,按照上面类似的思路,生成数据,进行聚类,并绘制聚类结果。代码如下:

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

X = np.random.randint(25,50,(25,2))
Y = np.random.randint(60,85,(25,2))
Z = np.vstack((X,Y))

# convert to np.float32
Z = np.float32(Z)

# define criteria and apply kmeans()
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
ret,label,center=cv2.kmeans(Z,2,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)

# Now separate the data, Note the flatten()
A = Z[label.ravel()==0]
B = Z[label.ravel()==1]

# Plot the data
plt.scatter(A[:,0],A[:,1])
plt.scatter(B[:,0],B[:,1],c = 'r')
plt.scatter(center[:,0],center[:,1],s = 80,c = 'y', marker = 's')
plt.xlabel('Height'),plt.ylabel('Weight')
plt.show()

聚类结果如下:





2017.11.17

猜你喜欢

转载自blog.csdn.net/guduruyu/article/details/78560009