OpenCV-Python 系列 五十七 | OpenCV中的K-Means聚类
本文是全系列中第47 / 63篇:OpenCV-Python
- OpenCV-Python 系列 四 | 视频入门
- OpenCV-Python 系列 十二 | 图像的几何变换
- OpenCV-Python 系列 二十 | 轮廓:入门
- OpenCV-Python 系列 二十八 | 直方图4:直方图反投影
- OpenCV-Python 系列 三十六 | 哈里斯角检测
- OpenCV-Python 系列 四十四 | 特征匹配 + 单应性查找对象
- OpenCV-Python 系列 五十二 | 理解K近邻
- OpenCV-Python 系列 六十 | 高动态范围
- OpenCV-Python 系列 五 | OpenCV中的绘图功能
- OpenCV-Python 系列 十三 | 图像阈值
- OpenCV-Python 系列 二十一 | 轮廓特征
- OpenCV-Python 系列 二十九 | 傅里叶变换
- OpenCV-Python 系列 三十七 | Shi-tomas拐角检测器和益于跟踪的特征
- OpenCV-Python 系列 四十五 | 如何使用背景分离方法
- OpenCV-Python 系列 五十三 | 使用OCR手写数据集运行KNN
- OpenCV-Python 系列 六十一 | 级联分类器
- OpenCV-Python 系列 六 | 鼠标作为画笔
- OpenCV-Python 系列 十四 | 图像阈值
- OpenCV-Python 系列 二十二 | 轮廓属性
- OpenCV-Python 系列 三十 | 模板匹配
- OpenCV-Python 系列 三十八 | SIFT尺度不变特征变换
- OpenCV-Python 系列 四十六 | Meanshift和Camshift
- OpenCV-Python 系列 五十四 | 理解SVM
- OpenCV-Python 系列 六十二 | 级联分类器训练
- OpenCV-Python 系列 七 | 轨迹栏作为调色板
- OpenCV-Python 系列 十五 | 图像平滑
- OpenCV-Python 系列 二十三 | 轮廓:更多属性
- OpenCV-Python 系列 三十一 | 霍夫线变换
- OpenCV-Python 系列 三十九 | SURF简介(加速的强大功能)
- OpenCV-Python 系列 四十七 | 光流
- OpenCV-Python 系列 五十五 | 使用OCR手写数据集运行SVM
- OpenCV-Python 系列 六十三 | OpenCV-Python Bindings 如何工作?
- OpenCV-Python 系列 八 | 图像的基本操作
- OpenCV-Python 系列 十六 | 形态学转换
- OpenCV-Python 系列 二十四 | 轮廓分层
- OpenCV-Python 系列 三十二 | 霍夫圈变换
- OpenCV-Python 系列 四十 | 用于角点检测的FAST算法
- OpenCV-Python 系列 四十八 | 相机校准
- OpenCV-Python 系列 五十六 | 理解K-Means聚类
- OpenCV-Python 系列 一 | 系列简介与目录
- OpenCV-Python 系列 九 | 图像上的算术运算
- OpenCV-Python 系列 十七 | 图像梯度
- OpenCV-Python 系列 二十五 | 直方图-1:查找、绘制和分析
- OpenCV-Python 系列 三十三 | 图像分割与Watershed算法
- OpenCV-Python 系列 四十一 | BRIEF(二进制的鲁棒独立基本特征)
- OpenCV-Python 系列 四十九 | 姿态估计
- OpenCV-Python 系列 五十七 | OpenCV中的K-Means聚类
- OpenCV-Python 系列 二 | 安装OpenCV-Python
- OpenCV-Python 系列 十 | 性能衡量和提升技术
- OpenCV-Python 系列 十八 | Canny边缘检测
- OpenCV-Python 系列 二十六 | 直方图-2:直方图均衡
- OpenCV-Python 系列 三十四 | 交互式前景提取使用GrabCut算法
- OpenCV-Python 系列 四十二 | ORB(面向快速和旋转的BRIEF)
- OpenCV-Python 系列 五十 | 对极几何
- OpenCV-Python 系列 五十八 | 图像去噪
- OpenCV-Python 系列 三 | 图像入门
- OpenCV-Python 系列 十一 | 改变颜色空间
- OpenCV-Python 系列 十九 | 图像金字塔
- OpenCV-Python 系列 二十七 | 直方图-3:二维直方图
- OpenCV-Python 系列 三十五 | 理解特征
- OpenCV-Python 系列 四十三 | 特征匹配
- OpenCV-Python 系列 五十一 | 立体图像的深度图
- OpenCV-Python 系列 五十九 | 图像修补
目标
- 了解如何在OpenCV中使用cv.kmeans()函数进行数据聚类
理解参数
输入参数
- sample:它应该是np.float32数据类型,并且每个功能都应该放在单个列中。
- nclusters(K):结束条件所需的簇数
- criteria:这是迭代终止条件。满足此条件后,算法迭代将停止。实际上,它应该是3个参数的元组。它们是
(type,max_iter,epsilon)
:
a. 终止条件的类型。它具有3个标志,如下所示:- cv.TERM_CRITERIA_EPS-如果达到指定的精度epsilon,则停止算法迭代。
- cv.TERM_CRITERIA_MAX_ITER-在指定的迭代次数max_iter之后停止算法。
- cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER-当满足上述任何条件时,停止迭代。
b. max_iter-一个整数,指定最大迭代次数。
c. epsilon-要求的精度 - attempts:该标志用于指定使用不同的初始标签执行算法的次数。该算法返回产生最佳紧密度的标签。该紧凑性作为输出返回。
- flags:此标志用于指定初始中心的获取方式。通常,为此使用两个标志:cv.KMEANS_PP_CENTERS和cv.KMEANS_RANDOM_CENTERS。
输出参数
1. 紧凑度:它是每个点到其相应中心的平方距离的总和。
2. 标签:这是标签数组(与上一篇文章中的“代码”相同),其中每个元素标记为“0”,“ 1” …..
3. 中心:这是群集中心的阵列。
现在,我们将通过三个示例了解如何应用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的精度时,就停止算法并返回答案。
# 定义终止标准 = ( type, max_iter = 10 , epsilon = 1.0 )
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
# 设置标志
flags = cv.KMEANS_RANDOM_CENTERS
# 应用K均值
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,以黄色绘制其质心。
# 现在绘制用红色'A',用蓝色绘制'B',用黄色绘制中心
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. 多特征数据
在前面的示例中,我们仅考虑了T恤问题的身高。在这里,我们将同时考虑身高和体重,即两个特征。
请记住,在以前的情况下,我们将数据制作为单个列向量。每个特征排列在一列中,而每一行对应于一个输入测试样本。
例如,在这种情况下,我们设置了一个大小为50×2的测试数据,即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))
# 将数据转换未 np.float32
Z = np.float32(Z)
# 定义停止标准,应用K均值
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)
# 现在分离数据, Note the flatten()
A = Z[label.ravel()==0]
B = Z[label.ravel()==1]
# 绘制数据
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()
我们得到如下结果:
3.颜色量化
颜色量化是减少图像中颜色数量的过程。这样做的原因之一是减少内存。有时,某些设备可能会受到限制,因此只能产生有限数量的颜色。同样在那些情况下,执行颜色量化。在这里,我们使用k均值聚类进行颜色量化。
这里没有新内容要解释。有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))
# 将数据转化为np.float32
Z = np.float32(Z)
# 定义终止标准 聚类数并应用k均值
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)
# 现在将数据转化为uint8, 并绘制原图像
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((img.shape))
cv.imshow('res2',res2)
cv.waitKey(0)
cv.destroyAllWindows()
我们可以看的K=8的结果
附加资源
练习
原创文章,作者:磐石,如若转载,请注明出处:https://panchuang.net/2020/04/02/opencv-python-%e7%b3%bb%e5%88%97-%e4%ba%94%e5%8d%81%e4%b8%83-opencv%e4%b8%ad%e7%9a%84k-means%e8%81%9a%e7%b1%bb/