📜  使用 K 均值聚类进行图像分割

📅  最后修改于: 2022-05-13 01:55:22.715000             🧑  作者: Mango

使用 K 均值聚类进行图像分割

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

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

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

用途:

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

图像分割还有很多用途。

在本文中,我们将使用一种称为 K 均值聚类的聚类方法对帝王蝶的图像进行分割。

K 均值聚类算法:

K 均值是一种聚类算法。聚类算法是无监督算法,这意味着没有可用的标记数据。它用于根据数据的相似程度来识别给定数据中的不同类或集群。与其他组中的数据点相比,同一组中的数据点与同一组中的其他数据点更相似。

K-means 聚类是最常用的聚类算法之一。这里, k表示簇的数量。

让我们看看 K-means 聚类是如何工作的——

  1. 选择要查找的簇数,即 k。
  2. 将数据点随机分配给 k 个集群中的任何一个。
  3. 然后计算簇的中心。
  4. 计算数据点到每个聚类中心的距离。
  5. 根据每个数据点与集群的距离,将数据点重新分配给最近的集群。
  6. 再次计算新的聚类中心。
  7. 重复步骤 4,5 和 6,直到数据点不改变集群,或者直到我们达到指定的迭代次数。

要求:

  • 确保你已经安装了Python、Numpy、Matplotlib 和 OpenCV。

代码:读入图像并将其转换为 RGB 图像。

python3
import numpy as np
import matplotlib.pyplot as plt
import cv2
 
%matplotlib inline
 
# Read in the image
image = cv2.imread('images/monarch.jpg')
 
# Change color to RGB (from BGR)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
 
plt.imshow(image)


python3
# Reshaping the image into a 2D array of pixels and 3 color values (RGB)
pixel_vals = image.reshape((-1,3))
 
# Convert to float type
pixel_vals = np.float32(pixel_vals)


python3
#the below line of code defines the criteria for the algorithm to stop running,
#which will happen is 100 iterations are run or the epsilon (which is the required accuracy)
#becomes 85%
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.85)
 
# then perform k-means clustering wit h number of clusters defined as 3
#also random centres are initially choosed for k-means clustering
k = 3
retval, labels, centers = cv2.kmeans(pixel_vals, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
 
# convert data into 8-bit values
centers = np.uint8(centers)
segmented_data = centers[labels.flatten()]
 
# reshape data into the original image dimensions
segmented_image = segmented_data.reshape((image.shape))
 
plt.imshow(segmented_image)



现在我们必须为 K 均值准备数据。该图像是一个 3 维形状,但要对其应用 k-means 聚类,我们需要将其重塑为一个 2 维数组。

代码:

蟒蛇3

# Reshaping the image into a 2D array of pixels and 3 color values (RGB)
pixel_vals = image.reshape((-1,3))
 
# Convert to float type
pixel_vals = np.float32(pixel_vals)

现在我们将实现用于分割图像的 K 均值算法。

代码:取k = 3,表示算法将识别图像中的3个簇。

蟒蛇3

#the below line of code defines the criteria for the algorithm to stop running,
#which will happen is 100 iterations are run or the epsilon (which is the required accuracy)
#becomes 85%
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.85)
 
# then perform k-means clustering wit h number of clusters defined as 3
#also random centres are initially choosed for k-means clustering
k = 3
retval, labels, centers = cv2.kmeans(pixel_vals, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
 
# convert data into 8-bit values
centers = np.uint8(centers)
segmented_data = centers[labels.flatten()]
 
# reshape data into the original image dimensions
segmented_image = segmented_data.reshape((image.shape))
 
plt.imshow(segmented_image)

输出:

现在,如果我们将k的值更改为6 ,我们将得到以下输出:

正如您所看到的,随着k值的增加,图像变得更加清晰和鲜明,因为 K-means 算法可以分类更多类别/颜色集群。当我们有一个小数据集时,K-means 聚类效果很好。它可以分割图像中的对象并提供更好的结果。但是当它应用于大型数据集(更多图像)时,它会在一次迭代中查看所有样本,这会导致占用大量时间。