使用层次聚类进行图像分割

Machine LearningMachine LearningBeginner
立即练习

This tutorial is from open-source community. Access the source code

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在本实验中,我们将学习如何使用层次聚类对二维图像进行分割。层次聚类是一种将相似数据点分组在一起的聚类算法。在图像分割的背景下,层次聚类可用于将具有相似颜色强度的像素分组在一起,这在识别图像中不同的区域或对象时可能会很有用。

我们将使用 Python 的 scikit-learn 库对硬币图像执行层次聚类。

虚拟机提示

虚拟机启动完成后,点击左上角切换到“笔记本”标签以访问 Jupyter Notebook 进行练习。

有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。

如果你在学习过程中遇到问题,请随时向 Labby 提问。课程结束后提供反馈,我们将立即为你解决问题。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/CoreModelsandAlgorithmsGroup(["Core Models and Algorithms"]) sklearn(("Sklearn")) -.-> sklearn/DataPreprocessingandFeatureEngineeringGroup(["Data Preprocessing and Feature Engineering"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/cluster("Clustering") sklearn/DataPreprocessingandFeatureEngineeringGroup -.-> sklearn/feature_extraction("Feature Extraction") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/cluster -.-> lab-49084{{"使用层次聚类进行图像分割"}} sklearn/feature_extraction -.-> lab-49084{{"使用层次聚类进行图像分割"}} ml/sklearn -.-> lab-49084{{"使用层次聚类进行图像分割"}} end

生成数据

我们将从生成数据开始。我们将使用 scikit-image 的 coins 数据集,它是一个硬币的二维灰度图像。我们将把图像调整为原始大小的 20% 以加快处理速度。

from skimage.data import coins
import numpy as np
from scipy.ndimage import gaussian_filter
from skimage.transform import rescale

orig_coins = coins()

## Resize it to 20% of the original size to speed up the processing
## Applying a Gaussian filter for smoothing prior to down-scaling
## reduces aliasing artifacts.

smoothened_coins = gaussian_filter(orig_coins, sigma=2)
rescaled_coins = rescale(
    smoothened_coins,
    0.2,
    mode="reflect",
    anti_aliasing=False,
)

X = np.reshape(rescaled_coins, (-1, 1))

定义数据结构

图像中的像素与其相邻像素相连。为了对图像执行层次聚类,我们需要定义数据的结构。我们可以使用 scikit-learn 的 grid_to_graph 函数来创建一个定义数据结构的连通性矩阵。

from sklearn.feature_extraction.image import grid_to_graph

connectivity = grid_to_graph(*rescaled_coins.shape)

计算聚类

定义好数据和连通性矩阵后,我们现在可以进行层次聚类了。我们将使用 scikit-learn 的 AgglomerativeClustering 类来执行聚类。我们将把聚类数量设置为 27,这是图像中硬币的数量。我们将使用 “ward” 链接方法,该方法会最小化正在合并的聚类之间距离的方差。我们还将传入在第二步中创建的连通性矩阵。

from sklearn.cluster import AgglomerativeClustering
import time as time

print("Compute structured hierarchical clustering...")
st = time.time()
n_clusters = 27  ## number of regions
ward = AgglomerativeClustering(
    n_clusters=n_clusters, linkage="ward", connectivity=connectivity
)
ward.fit(X)
label = np.reshape(ward.labels_, rescaled_coins.shape)
print(f"Elapsed time: {time.time() - st:.3f}s")
print(f"Number of pixels: {label.size}")
print(f"Number of clusters: {np.unique(label).size}")

绘制结果

最后,我们可以在图像上绘制结果。我们将使用 matplotlib 来绘制缩放后的图像和聚类的轮廓。我们将遍历每个聚类并绘制该聚类中像素的轮廓。

import matplotlib.pyplot as plt

plt.figure(figsize=(5, 5))
plt.imshow(rescaled_coins, cmap=plt.cm.gray)
for l in range(n_clusters):
    plt.contour(
        label == l,
        colors=[
            plt.cm.nipy_spectral(l / float(n_clusters)),
        ],
    )
plt.axis("off")
plt.show()

总结

在本实验中,我们学习了如何使用层次聚类对二维图像进行分割。我们生成了数据,定义了数据结构,执行了层次聚类,并在图像上绘制了结果。这项技术在识别图像中不同的区域或对象时可能会很有用。