前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用K-Means聚类进行图像分割(OpenCV代码演示)

使用K-Means聚类进行图像分割(OpenCV代码演示)

作者头像
Color Space
发布2024-04-12 16:01:01
3760
发布2024-04-12 16:01:01
举报

图像分割:

在计算机视觉中,图像分割是将图像划分为多个片段的过程。分割图像的目标是将图像的表示改变为更有意义且更易于分析的东西。它通常用于定位对象和创建边界。

处理整个图像并不是一个好主意,因为图像中的许多部分可能不包含任何有用的信息。因此,通过对图像进行分割,我们可以只利用重要的片段进行处理。

图像基本上是一组给定的像素。在图像分割中,具有相似属性的像素被分组在一起。图像分割为图像中的对象创建像素级掩模,这使我们能够更全面、更细致地了解对象。

用途:

  • 用于自动驾驶汽车。如果没有涉及分割的对象检测,自动驾驶就不可能实现。
  • 用于医疗保健行业。有助于分割癌细胞和肿瘤,从而可以衡量其严重程度。

图像分割还有很多用途。

现在,让我们探索一种使用 K-Means 聚类算法和 OpenCV 读取图像并对图像的不同区域进行聚类的方法。

所以基本上我们将执行颜色聚类和 Canny 边缘检测。

颜色聚类

加载所有需要的库:

代码语言:javascript
复制
import numpy as np
import cv2
import matplotlib.pyplot as plt

下一步是在 RGB 颜色空间中加载图像

代码语言:javascript
复制
Original_image = cv2.imread("/Users/path/../image1.jpg")

原图:

我们需要将图像从 RGB 颜色空间转换为 HSV 才能继续工作。为什么??

根据维基百科,数字图像中对象颜色的 R、G 和 B 分量都与照射到对象的光量相关,因此,这些分量之间的图像描述使得对象辨别变得困难。用色调/亮度/色度或色调/亮度/饱和度进行描述通常更相关。

代码语言:javascript
复制
img=cv2.cvtColor(original_image,cv2.COLOR_BGR2RGB)

接下来,将 MxNx3 图像转换为 Kx3 矩阵,其中 K=MxN 并且每一行现在都是 RGB 3-D 空间中的向量。

代码语言:javascript
复制
vectorized = img.reshape((-1,3))

我们将 unit8 值转换为浮点型,因为这是 OpenCV k-means 方法的要求。

代码语言:javascript
复制
vectorized = np.float32(vectorized)

我们将以 k = 3 进行聚类,因为如果你看上面的图像,它有 3 种颜色:绿色的草地和森林、蓝色的大海和绿蓝色的海岸。

定义标准、簇数 (K) 并应用 k-means()

代码语言:javascript
复制
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0

OpenCV 提供了cv2.kmeans( samples, nclusters(K), criteria, attempts, flags ) 函数用于颜色聚类。

1.样本:应为np.float32数据类型,并且每个特征应放在单列中。

2. nclusters(K):最后需要的簇数

3. 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 — 当满足上述任何条件时停止迭代。

4. attempts:标志指定使用不同初始标签执行算法的次数。该算法返回产生最佳紧凑性的标签。这种紧凑性作为输出返回。

5. flags:该标志用于指定如何取初始中心。通常为此使用两个标志:cv.KMEANS_PP_CENTERS和cv.KMEANS_RANDOM_CENTERS。

代码语言:javascript
复制
K = 3
attempts=10
ret,label,center=cv2.kmeans(vectorized,K,None,criteria,attempts,cv2.KMEANS_PP_CENTERS)

现在转换回 uint8。

代码语言:javascript
复制
center = np.uint8(center)

接下来,我们必须访问标签来重新生成聚类图像

代码语言:javascript
复制
res = center[label.flatten()] 
result_image = res.reshape((img.shape))

现在让我们可视化 K=3 时的输出结果

代码语言:javascript
复制
figure_size = 15
plt.figure(figsize=(figure_size,figure_size))
plt.subplot(1,2,1),plt.imshow(img)
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(1,2,2),plt.imshow(result_image)
plt.title('Segmented Image when K = %i' % K), plt.xticks([]), plt.yticks([])
plt.show()

因此,该算法将我们的原始图像分为三种主色。

让我们看看当我们改变 K=5 的值时会发生什么:

让我们进入下一部分,即 Canny 边缘检测。

Canny边缘检测:它是一种图像处理方法,用于检测图像中的边缘,同时抑制噪声。

Canny边缘检测算法由5个步骤组成:

  • 梯度计算
  • 非极大值抑制
  • 双门槛
  • 通过磁滞进行边缘跟踪

OpenCV提供了cv2.Canny(image,threshold1,threshold2)函数用于边缘检测。

第一个参数是我们的输入图像。第二个和第三个参数分别是我们的最小和最大阈值。

该函数在输入图像(8 位输入图像)中查找边缘,并使用 Canny 算法将它们标记在输出图边缘中。阈值1和阈值2之间的最小值用于边缘链接。最大值用于查找强边缘的初始段。

代码语言:javascript
复制
edges = cv2.Canny(img,150,200)
plt.figure(figsize=(figure_size,figure_size))
plt.subplot(1,2,1),plt.imshow(img)
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(1,2,2),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()

处理效果如下:

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-04-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV与AI深度学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档