当前位置 : 主页 > 编程语言 > python >

opencv K均值聚类(python)

来源:互联网 收集:自由互联 发布时间:2022-06-15
K均值聚类 预测的是一个离散值时,做的工作就是“分类”。 预测的是一个连续值时,做的工作就是“回归”。 机器学习模型还可以将训练集中的数据划分为若干个组,每个组被称为一

K均值聚类

  • 预测的是一个离散值时,做的工作就是“分类”。
  • 预测的是一个连续值时,做的工作就是“回归”。

机器学习模型还可以将训练集中的数据划分为若干个组,每个组被称为一个“簇(cluster)”。这种学习方式被称为“聚类(clusting)”,它的重要特点是在学习过程中不需要用标签对训练样本进行标注。也就是说,学习过程能够根据现有训练集自动完成分类(聚类)。

根据训练数据是否有标签,可以将学习划分为监督学习和无监督学习。


K近邻、支持向量机都是监督学习,提供有标签的数据给算法学习,然后对数据分类

聚类是无监督学习,事先并不知道分类标签是什么,直接对数据分类。


聚类能够将具有相似属性的对象划分到同一个集合(簇)中。

聚类方法能够应用于所有对象,簇内的对象越相似,聚类算法的效果越好。

K均值聚类的基本步骤

K均值聚类是一种将输入数据划分为k个簇的简单的聚类算法,该算法不断提取当前分类的中心点(也称为质心或重心),并最终在分类稳定时完成聚类。

从本质上说,K均值聚类是一种迭代算法。

在实际处理过程中需要进行多轮的迭代,直到分组稳定不再发生变化,即可认为分组完成。

K均值聚类算法的基本步骤如下:

  • 随机选取k个点作为分类的中心点。
  • 将每个数据点放到距离它最近的中心点所在的类中。
  • 重新计算各个分类的数据点的平均值,将该平均值作为新的分类中心点。
  • 重复步骤2和步骤3,直到分类稳定。

  • 可以是随机选取k个点作为分类的中心点,也可以是随机生成k个并不存在于原始数据中的数据点作为分类中心点。


    距离最近: 要进行某种形式的距离计算。(在具体实现时,可以根据需要采用不同形式的距离度量方法。)

    K均值聚类模块

    OpenCV提供了函数cv2.kmeans()来实现K均值聚类。

    该函数的语法格式为:

    retval, bestLabels, centers=cv2.kmeans(data, K, bestLabels, criteria, attempts,
    flags)
    • data:输入的待处理数据集合,应该是np.float32类型,每个特征放在单独的一列中。
    • K:要分出的簇的个数,即分类的数目,最常见的是K=2,表示二分类。
    • bestLabels:表示计算之后各个数据点的最终分类标签(索引)。实际调用时,参数bestLabels的值设置为None。
    • criteria:算法迭代的终止条件。当达到最大循环数目或者指定的精度阈值时,算法停止继续分类迭代计算。该参数由3个子参数构成,分别为type、max_iter和eps。
    • 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:表示选择初始中心点的方法,主要有以下3种。
    • cv2.KMEANS_RANDOM_CENTERS:随机选取中心点。
    • cv2.KMEANS_PP_CENTERS:基于中心化算法选取中心点。
    • cv2.KMEANS_USE_INITIAL_LABELS:使用用户输入的数据作为第一次分类中心点;如果算法需要尝试多次(attempts 值大于1时),后续尝试都是使用随机值或者半随机值作为第一次分类中心点。
    • retval:距离值(也称密度值或紧密度),返回 每个点到相应中心点距离的平方和(是一个数)。
    • bestLabels:各个数据点的最终分类标签(索引)。
    • centers:每个分类的中心点数据。

    简单例子

    例1:

    随机生成一组数据,使用函数cv2.kmeans()对其分类。

    • 一组数据在[0,50]区间
    • 另一组数据在[200,250]区间
    • 使用函数cv2.kmeans()对它们分类。

    主要步骤如下:

  • 数据预处理
    使用随机函数随机生成两组数据,并将它们转换为函数cv2.kmeans()可以处理的格式。
  • 设置参数
    设置函数cv2.kmeans()的参数形式。将参数criteria的值设置为“(cv2.TERM_CRITERIA_EPS+ cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)”,在达到一定次数或者满足一定精度时终止迭代。
  • 调用函数cv2.kmeans()
    调用函数cv2.kmeans(),获取返回值,用于后续步骤的操作。
  • 确定分类
    根据函数cv2.kmeans()返回的标签(“0”和“1”),将原始数据分为两组
  • 显示结果
    绘制经过分类的数据及中心点,观察分类结果。
  • 完整程序:

    import numpy as np
    import cv2
    from matplotlib import pyplot as plt
    # 随机生成两组数组
    # 生成60个值在[0,50]内的数据
    num1 = np.random.randint(0,50,60)
    # 生成60个值在[200,250]内的数据
    num2 = np.random.randint(200,250,60)
    # 组合数据为num
    num = np.hstack((num1, num2))
    # 使用reshape函数将其转换为(120,1)
    num = num.reshape((120,1)) #每个数据为1列
    # 转换为float32类型
    num = np.float32(num)
    # 调用kmeans模块
    # 设置参数criteria的值
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
    # 设置参数flags的值
    flags = cv2.KMEANS_RANDOM_CENTERS
    # 调用函数kmeans
    retval, bestLabels, centers = cv2.kmeans(num,2, None, criteria,10, flags)

    # 打印返回值
    print(retval)
    print(bestLabels)
    print(centers)

    # 获取分类结果
    n1 = num[bestLabels==0]
    n2 = num[bestLabels==1]

    # 绘制分类结果
    # 绘制原始数据
    plt.plot(np.ones(len(n1)),n1,'ro')
    plt.plot(np.ones(len(n2)),n2,'bo')
    # 绘制中心点
    #plt.plot([1],centers[0],'rx')
    #plt.plot([1],centers[1],'bx')
    plt.show()

    例2:

    有两种物体:

    • 物体1的长和宽都在 [0,20] 内
    • 物体2的长和宽都在[40,60] 内

    使用随机数模拟两种物体的长度和宽度,并使用函数cv2.kmeans()对它们分类。

    根据题目要求,主要步骤如下:

  • 随机生成数据,并将它们转换为函数cv2.kmeans()可以处理的形式。
  • 设置函数cv2.kmeans()的参数形式。
  • 调用函数cv2.kmeans()。
  • 根据函数cv2.kmeans()的返回值,确定分类结果。
  • 绘制经过分类的数据及中心点,观察分类结果。
  • import numpy as np
    import cv2
    from matplotlib import pyplot as plt
    # 随机生成两组数值
    #长和宽都在[0,20]内
    m1 = np.random.randint(0,20, (30,2))
    #长和宽的大小都在[40,60]
    m2 = np.random.randint(40,60, (30,2))
    # 组合数据
    m = np.vstack((m1, m2))
    # 转换为float32类型
    m = np.float32(m)
    # 调用kmeans模块
    # 设置参数criteria值
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
    # 调用kmeans函数
    ret, label, center=cv2.kmeans(m,2, None, criteria,10, cv2.KMEANS_RANDOM_CENTERS)

    '''
    #打印返回值
    print(ret)
    print(label)
    print(center)
    '''
    # 根据kmeans的处理结果,将数据分类,两大类
    res1 = m[label.ravel()==0]
    res2 = m[label.ravel()==1]
    # 绘制分类结果数据及中心点
    plt.scatter(res1[:,0], res1[:,1], c = 'g', marker = 's')
    plt.scatter(res2[:,0], res2[:,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()

    例3:

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

    需要对灰度图像内的色彩进行分类,将所有的像素点划分为两类。然后,用这两类的中心点像素值替代原有像素值,满足题目的要求。

    主要步骤如下:

  • 图像预处理
    读取图像,并将图像转换为函数cv2.kmeans()可以处理的形式。
  • 在读取图像时,如果是3个通道的RGB图像,需要将图像的RGB值处理为一个单独的特征值。具体实现时,用函数cv2.reshape()完成对图像特征值的调整。

  • 为了满足函数cv2.kmeans()的要求,需要将图像的数据类型转换为numpy.float32类型。
  • 设置函数cv2.kmeans()的参数形式
    设置参数criteria的值为“(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)”,让函数cv2.kmeans()在达到一定精度或者达到一定迭代次数时,即停止迭代。
    设置参数K的值为2,将所有像素划分为两类。
  • 调用函数cv2.kmeans()
    调用函数cv2.kmeans(),得到距离值、分类中心点和分类标签,用于后续操作。
  • 值替换
    将像素点的值替换为当前分类的中心点的像素值。
  • 显示变换前后的图像
    分别显示原始图像和二值化图像。
  • import numpy as np
    import cv2
    import matplotlib.pyplot as plt
    # 读取待处理图像
    img = cv2.imread('./img/hand2.png')
    # 使用reshape将一个像素点的RGB值作为一个单元处理
    data = img.reshape((-1,3)) # n行 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[:,:,::-1])
    plt.axis('off')
    plt.subplot(122)
    plt.imshow(res2[:,:,::-1])
    plt.axis('off')
    plt.show()


    调整程序中的K值,就能改变图像的显示结果。例如,K=8,则可以让图像显示8个灰度级。


    上一篇:opencv K近邻(python)
    下一篇:没有了
    网友评论