Note
Go to the end to download the full example code. or to run this example in your browser via Binder
用于图像分割的谱聚类#
在这个示例中,生成了一幅包含相连圆形的图像,并使用谱聚类将这些圆形分开。
在这些设置中,谱聚类 方法解决了所谓的“归一化图割”问题:图像被视为一个由相连体素组成的图,而谱聚类算法相当于选择定义区域的图割,同时最小化沿割线的梯度与区域体积的比率。
由于算法试图平衡体积(即平衡区域大小),如果我们使用不同大小的圆形,分割将会失败。
此外,由于图像的强度或其梯度中没有有用的信息,我们选择在一个仅由梯度弱信息化的图上执行谱聚类。这接近于对图执行 Voronoi 分区。
另外,我们使用对象的掩码来将图限制在对象的轮廓上。在这个示例中,我们感兴趣的是将对象彼此分开,而不是将它们与背景分开。
# 作者:scikit-learn 开发者
# SPDX-License-Identifier:BSD-3-Clause
生成数据#
import numpy as np
l = 100
x, y = np.indices((l, l))
center1 = (28, 24)
center2 = (40, 50)
center3 = (67, 58)
center4 = (24, 70)
radius1, radius2, radius3, radius4 = 16, 14, 15, 14
circle1 = (x - center1[0]) ** 2 + (y - center1[1]) ** 2 < radius1**2
circle2 = (x - center2[0]) ** 2 + (y - center2[1]) ** 2 < radius2**2
circle3 = (x - center3[0]) ** 2 + (y - center3[1]) ** 2 < radius3**2
circle4 = (x - center4[0]) ** 2 + (y - center4[1]) ** 2 < radius4**2
绘制四个圆#
img = circle1 + circle2 + circle3 + circle4
# 我们使用一个限制在前景的掩码:我们在这里感兴趣的问题不是将物体从背景中分离出来,而是将它们彼此分离。
mask = img.astype(bool)
img = img.astype(float)
img += 1 + 0.2 * np.random.randn(*img.shape)
将图像转换为图,其中边的值为梯度值。
from sklearn.feature_extraction import image
graph = image.img_to_graph(img, mask=mask)
取梯度的递减函数,得到接近于Voronoi分割的分割结果
graph.data = np.exp(-graph.data / graph.data.std())
在这里,我们使用 arpack 求解器执行谱聚类,因为在这个例子中 amg 在数值上不稳定。然后我们绘制结果。
import matplotlib.pyplot as plt
from sklearn.cluster import spectral_clustering
labels = spectral_clustering(graph, n_clusters=4, eigen_solver="arpack")
label_im = np.full(mask.shape, -1.0)
label_im[mask] = labels
fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(10, 5))
axs[0].matshow(img)
axs[1].matshow(label_im)
plt.show()
绘制两个圆#
在这里我们重复上述过程,但只考虑我们生成的前两个圆。请注意,这样会导致圆之间的分离更加清晰,因为在这种情况下区域大小更容易平衡。
img = circle1 + circle2
mask = img.astype(bool)
img = img.astype(float)
img += 1 + 0.2 * np.random.randn(*img.shape)
graph = image.img_to_graph(img, mask=mask)
graph.data = np.exp(-graph.data / graph.data.std())
labels = spectral_clustering(graph, n_clusters=2, eigen_solver="arpack")
label_im = np.full(mask.shape, -1.0)
label_im[mask] = labels
fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(10, 5))
axs[0].matshow(img)
axs[1].matshow(label_im)
plt.show()
Total running time of the script: (0 minutes 0.395 seconds)
Related examples
将希腊硬币的图片分割成多个区域
压缩感知:具有L1先验(Lasso)的断层扫描重建
在线学习人脸部件的字典
使用核PCA进行图像去噪