介绍K均值聚类模块的语法,并通过数据的分类以及图像处理案例来了解其具体的使用。

K均值聚类模块

OpenCV中,提供了cv2.kmeans()来实现L均值聚类。该函数的语法是:

retval,bestLabels,centers= cv2.kmeans(data, K, bestLabels, criteria, attempts, flags)

含义:

  • data: 输入的待处理数据集合,应该是np.float32类型。每个特征放在单独的一列中
  • k: 要分出来的簇的个数
  • bestLabels: 表示计算之后各个数据点的最终分类标签(索引)。实际调用时,该参数设置为None
  • criteria:算法迭代的终止条件。最大循环次数或者指定的精度阈值。由三个子参数组成:
    • type表示终止的类型,可以是三种情况:
      • cv2.TERM_CRITERIA_EPS:精度满足eps时,停止迭代
      • cv2.TERM_CRITERIA_MAX_ITER:迭代次数超过阈值max_iter时,停止迭代
      • cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER:上面的条件任意一个满足时,停止跌倒
    • max_iter:最大的迭代次数
    • eps:精确度的阈值
  • attempts:在具体实现时,为了获得最佳分类效果,可能需要使用不同地初始分类值就行多次尝试。指定attempts的值,可以让算法使用不同的初始值进行多次(attempts)尝试
  • flags:表示选择初始中心点的方法,主要有三种:
    • cv2.KMEANS_RANDOM_CENTERS:随机选取中心点
    • cv2.KMEANS_PP_CENTERS:基于中心优化算法选取中心点
    • cv2.KMEANS_USE_INITIAL_LABELS:使用用户输入的数据作为第一次分类中心点,如果需要多次attempt,后续使用的都是随机值或者半随机值作为第一次分类中心点。
  • retval:距离值(密度值),返回每个点到相应中心点距离的平方和
  • bestLabels:各个数据点的最终分类标签
  • centers:每个分类的中心点数据

K-Means分类案例

例1:有一堆米粒,按照长度和宽度对其进行分类。

为了方便理解,假设有两种米粒,一种是XM(长和宽都在[0,20]之间),一种是DM([长和宽都在[40,60]之间])。使用随机数模拟两种米粒的长度和宽度,并使用函数cv2.kmeans()对其分类。

步骤:

  • 随机生成两种米粒的数据,转换其格式,使得kmeans函数可以处理
  • 设置函数cv2.kmeans()的参数形式
  • 调用函数cv2.kmeans()
  • 根据cv2.kmeans()的返回值,确定分类的结果
import numpy as np
import cv2
from matplotlib import pyplot as plt
#随机生成两组数值
#xiaomi组,长和宽的大小都在[0,20]
xiaomi = np.random.randint(0,20,(30,2))

#dami组,长和宽的大小都在[40,60]
dami = np.random.randint(40,60,(30,2))

#组合数据
MI = np.vstack((xiaomi,dami))
# 转换为float32类型
MI = np.float32(MI)

# 调用kmeans模块
#设置参数criteria值
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
#调用kmeans函数
ret,label,center=cv2.kmeans(MI,2,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)
'''
#打印返回值
print(ret)
print(label)
print(center)
'''
# 根据kmeans处理结果,将数据分类,分为XM和DM两大类
XM = MI[label.ravel()==0]
DM = MI[label.ravel()==1]

# 绘制分类结果数据及中心点
plt.scatter(XM[:,0],XM[:,1],c = 'g', marker = 's')
plt.scatter(DM[:,0],DM[:,1],c = 'r', marker = 'o')
plt.scatter(center[0,0],center[0,1],s = 200,c = 'b', marker = 'o')
plt.scatter(center[1,0],center[1,1],s = 200,c = 'b', marker = 's')
plt.xlabel('Height'),plt.ylabel('Width')
plt.show()

聚类结果

大点的圆形以及方框是对应类别的中心。

例2:使用函数cv2.kmeans()将灰度图像处理为只有两个灰度级的二值图像。

步骤:

1、图像预处理

读取图像,并将图像转换为函数cv2.kmeans能处理的形式。

在读取图像时,如果是3个通道的RGB图像,需要将其处理为一个单独的特征值。可以用reshape函数。再将其转换为numpy.float32类型。

2、设置函数cv2.kmeans()的参数

设置参数criteria的参数为(cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER,10,1.0)

3、调用函数cv2.kmeans(),得到距离值、分类中心和分类标签

4、值替换。将当前值替换为当前分类的中心点的像素值。

5、显示变换前后的图像

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

#读取待处理图像
img = cv2.imread('lena.bmp')

#使用reshape将一个RGB像素点值的三个值作为一个单元
data = img.reshape(-1,3)
#转换为kmeans可以处理的类型
data = np.float32(data)

#调用kmeans模块
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K =2
ret,label,center=cv2.kmeans(data,K,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)
# 转换为uint8数据类型,将每个像素点值都赋值为当前组的中心点值
#将center的值转换为uint8
center = np.uint8(center)
#使用center内的值替换原有像素点值
res1 = center[label.flatten()]
#使用reshape调整替换后图像
res2 = res1.reshape((img.shape))
#显示处理结果
plt.subplot(121)
plt.imshow(img)
plt.axis('off')
plt.subplot(122)
plt.imshow(res2)
plt.axis('off')

plt.show()

处理结果


-1的意思是对应的维度未知,在运算过程中会根据给出的维度自动求得。具体可以看下面这篇文章:

Python中reshape函数参数-1的意思?



博主个人公众号
版权声明 ▶ 本网站名称:陶小桃Blog
▶ 本文链接:https://www.52txr.cn/2022/CVkmeans2.html
▶ 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行核实删除。
▶ 转载本站文章需要遵守:商业转载请联系站长,非商业转载请注明出处!!

最后修改:2022 年 05 月 25 日
如果觉得我的文章对你有用,请随意赞赏