当前位置: 首页 > article >正文

opencv - py_ml - py_kmeans

文章目录

  • 1.理解 K-Means 聚类
    • 目标
    • 理论
      • T 恤尺码问题
      • 它是如何工作的?
    • 其他资源
  • 2.OpenCV 中的 K-Means 聚类
    • 目标
    • 理解参数
      • 输入参数
      • 输出参数

1.理解 K-Means 聚类

目标

在本章中,我们将理解 K-Means 聚类的概念、其工作原理等。

理论

我们将通过一个常用的例子来处理这个问题。

T 恤尺码问题

假设一家公司即将向市场推出一款新的 T 恤。显然,他们必须生产不同尺寸的款式以满足各种身材的人。因此,该公司制作了人们的身高和体重数据,并将它们绘制在图表上,如下所示:
在这里插入图片描述

公司无法生产所有尺寸的 T 恤。相反,他们将人们分为小号、中号和大号,并只生产适合所有人的这 3 种型号。将人们分成三组可以通过 k 均值聚类来完成,算法会为我们提供最佳的 3 种尺寸,这将满足所有人的需求。如果不能,公司可以将人们分成更多组,可能是五组,依此类推。查看下图:

在这里插入图片描述

它是如何工作的?

该算法是一个迭代过程。我们将借助图像逐步解释它。

考虑如下一组数据(您可以将其视为 T 恤问题)。我们需要将此数据聚类为两组。

在这里插入图片描述

步骤:1 - 算法随机选择两个质心, C 1 C1 C1 C 2 C2 C2(有时,任何两个数据都被视为质心)。

步骤:2 - 计算每个点到两个质心的距离。如果测试数据更接近 C 1 C1 C1,则该数据标记为“0”。如果它更接近 C 2 C2 C2,则标记为“1”(如果有更多质心,则标记为“2”、“3”等)。

在我们的例子中,我们将所有“0”标记为红色,将“1”标记为蓝色。因此,经过上述操作后,我们得到以下图像。

在这里插入图片描述

步骤:3 - 接下来,我们分别计算所有蓝点和红点的平均值,这将是我们的新质心。也就是说, C 1 C1 C1 C 2 C2 C2 移至新计算的质心。(请记住,显示的图像不是真实值,也不是真实比例,仅用于演示)。

再次使用新质心执行步骤 2,并将数据标记为“0”和“1”。

因此,我们得到以下结果:

在这里插入图片描述

现在,步骤 2步骤 3 迭代,直到两个质心都收敛到固定点。
(或者,根据我们提供的标准,例如最大迭代次数,或达到特定精度等,可能会停止。) 这些点使得测试数据和其对应质心之间的距离总和最小。或者简单地说,
C 1 ↔ R e d _ P o i n t s C1 \leftrightarrow Red\_Points C1Red_Points C 2 ↔ B l u e _ P o i n t s C2 \leftrightarrow Blue\_Points C2Blue_Points 之间的距离总和最小。

[ m i n i m i z e    [ J = ∑ A l l   R e d _ P o i n t s d i s t a n c e ( C 1 , R e d _ P o i n t ) + ∑ A l l   B l u e _ P o i n t s d i s t a n c e ( C 2 , B l u e _ P o i n t ) ] ] [minimize \;\bigg[J = \sum_{All\: Red\_Points}distance(C1,Red\_Point) + \sum_{All\: Blue\_Points}distance(C2,Blue\_Point)\bigg]] [minimize[J=AllRed_Pointsdistance(C1,Red_Point)+AllBlue_Pointsdistance(C2,Blue_Point)]]

最终结果几乎如下所示:
在这里插入图片描述
因此,这只是对 K-Means 聚类的直观理解。有关更多详细信息和数学解释,请阅读任何标准机器学习教科书或查看其他资源中的链接。它只是 K-Means 聚类的顶层。对该算法有很多修改,例如如何选择初始质心,如何加快迭代过程等。

其他资源

  • 机器学习课程,Andrew Ng 教授的视频讲座(部分图片取自此处)

2.OpenCV 中的 K-Means 聚类

目标

  • 学习使用 OpenCV 中的 cv.kmeans() 函数进行数据聚类

理解参数

输入参数

  • samples :它应该是 np.float32 数据类型,并且每个特征应该放在一个列中。
  • nclusters(K) :结束时所需的聚类数
  • criteria :它是迭代终止标准。当满足此标准时,算法迭代停止。实际上,它应该是 3 个参数的元组。它们是 `( type, max_iter, epsilon )`:
    • 终止标准类型。它有 3 个标志,如下所示:
      • cv.TERM_CRITERIA_EPS - 如果达到指定的准确度 epsilon,则停止算法迭代。
      • cv.TERM_CRITERIA_MAX_ITER - 在指定的迭代次数 max_iter 后停止算法。
      • cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER - 当满足上述任何条件时停止迭代。
    • max_iter - 指定最大迭代次数的整数。
    • epsilon - 所需准确度
  • attempts:标志,用于指定使用不同初始标签执行算法的次数。算法返回产生最佳紧凑度的标签。此紧凑度作为输出返回。
  • flags:此标志用于指定如何获取初始中心。通常,为此使用两个标志:cv.KMEANS_PP_CENTERScv.KMEANS_RANDOM_CENTERS

输出参数

  • 紧凑性:它是每个点到其相应中心的平方距离之和。

  • 标签:这是标签数组(与上一篇文章中的“代码”相同),其中每个元素标记为“0”、“1”…

  • 中心:这是聚类中心的数组。

现在我们将通过三个示例了解如何应用 K-Means 算法。

  1. 仅具有一个特征的数据

考虑一下,您有一组仅具有一个特征的数据,即一维数据。例如,我们可以以 T 恤问题为例,您仅使用人的身高来决定 T 恤的尺寸。

因此我们首先创建数据并在 Matplotlib 中绘制它

import numpy as np
import cv2 as cv
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()

因此,我们有“z”,它是一个大小为 50 的数组,值范围从 0 到 255。我已将“z”重塑为列向量。当存在多个特征时,它将更有用。然后我制作了 np.float32 类型的数据。

我们得到以下图像:

在这里插入图片描述

现在我们应用 KMeans 函数。在此之前,我们需要指定标准。我的标准是这样的:每当运行 10 次算法迭代,或达到 epsilon = 1.0 的精度时,就停止算法并返回答案。

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

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

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

这给了我们紧凑性、标签和中心。在本例中,我得到的中心是 60 和 207。标签的大小与测试数据的大小相同,其中每个数据将根据其质心标记为“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()

下面是我们得到的输出:

在这里插入图片描述

  1. 具有多个特征的数据

在前面的例子中,我们只取 T 恤问题的身高。在这里,我们将取身高和体重,即两个特征。

记住,在前面的例子中,我们将数据制成单列向量。每个特征排列在一列中,而每行对应一个输入测试样本。

例如,在本例中,我们设置了一个大小为 50x2 的测试数据,其中包含 50 个人的身高和体重。第一列对应所有 50 个人的身高,第二列对应他们的体重。第一行包含两个元素,其中第一个元素是第一个人的身高,第二个元素是他的体重。同样,其余行对应其他人的身高和体重。
查看下图:
在这里插入图片描述

现在我直接转到代码:

import numpy as np
import cv2 as cv
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 = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
ret,label,center=cv.kmeans(Z,2,None,criteria,10,cv.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()

以下是我们得到的输出:
在这里插入图片描述

  1. 颜色量化

颜色量化是减少图像中颜色数量的过程。这样做的原因之一是为了减少内存。有时,某些设备可能存在限制,因此只能产生有限数量的颜色。在这些情况下,也会执行颜色量化。这里我们使用 k-means 聚类进行颜色量化。

这里没有什么新东西需要解释。有 3 个特征,例如 R、G、B。因此,我们需要将图像重塑为 Mx3 大小的数组(M 是图像中的像素数)。聚类之后,我们将质心值(也是 R、G、B)应用于所有像素,这样生成的图像将具有指定数量的颜色。我们再次需要将其重塑回原始图像的形状。
以下是代码:

import numpy as np
import cv2 as cv

img = cv.imread('home.jpg')
Z = img.reshape((-1,3))

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

# define criteria, number of clusters(K) and apply kmeans()
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 8
ret,label,center=cv.kmeans(Z,K,None,criteria,10,cv.KMEANS_RANDOM_CENTERS)

# Now convert back into uint8, and make original image
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((img.shape))

cv.imshow('res2',res2)
cv.waitKey(0)
cv.destroyAllWindows()

当 K=8 时,结果如下:

在这里插入图片描述


http://www.kler.cn/a/370241.html

相关文章:

  • Vue.js从入门到精通 — 基础知识
  • 医学影像基础:常见的医学影像学术语和概念
  • 商场应急管理:SpringBoot技术解决方案
  • 后端:Spring-1
  • 智能EDA小白从0开始 —— DAY30 冉谱微RFIC-GPT
  • canvas基础学习(鼠标点位拖拽)
  • 为什么有的说法是STM32有60个外部中断,有的说法是有23个中断
  • vscode中提升效率的插件扩展——待更新
  • 基于Distil-Whisper的实时ASR【自动语音识别】
  • python实战项目47:Selenium采集百度股市通数据
  • 电商 API 接口:提升用户体验的关键路径深度解析
  • AtCoder ABC376A-D题解
  • 雷池社区版compose文件配置讲解--fvm
  • 分布式并发场景的核心问题与解决方案
  • Java | Leetcode Java题解之第516题最长回文子序列
  • Camp4-L0:Linux 前置基础
  • 招商银行实时汇率查询接口-外汇实时汇率API-外汇实时汇率
  • 云联网对等连接--实现内网互通
  • 解决cuda环境使用dgl
  • ImportError: cannot import name ‘Sequential‘ from ‘keras.models‘