在本教程中,将通过一个示例来展示如何利用Ward分层聚类算法对一个包含多个硬币的2D图像进行分割。这种聚类方法在空间上是有限制的,确保每个分割区域都是连续的。分层聚类是一种常用的图像分割技术,它能够将图像中的相似区域组合在一起,形成不同的聚类。
首先,需要生成或获取硬币图像的数据。在这个示例中,使用了skimage.data
模块中的coins
函数来获取原始的硬币图像。为了加快处理速度,将图像缩小到原始大小的20%,并在缩小之前应用高斯滤波器进行平滑处理,以减少混叠伪影。
from skimage.data import coins
orig_coins = coins()
import numpy as np
from scipy.ndimage import gaussian_filter
from skimage.transform import rescale
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))
在进行聚类之前,需要定义数据的结构。在这个示例中,使用sklearn.feature_extraction.image
模块中的grid_to_graph
函数来创建一个图,表示像素与其邻居之间的连接关系。
from sklearn.feature_extraction.image import grid_to_graph
connectivity = grid_to_graph(*rescaled_coins.shape)
接下来,使用sklearn.cluster
模块中的AgglomerativeClustering
类来执行分层聚类。设置了聚类的数量为27,并指定了Ward链接方法和之前定义的连接性。
import time
from sklearn.cluster import AgglomerativeClustering
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.pyplot
模块来展示聚类的结果。通过在原始图像上绘制轮廓线,可以清晰地看到每个硬币的分割效果。
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()
通过上述代码,可以看到每个硬币都被成功地分割出来,尽管设置的聚类数量比实际的硬币数量要多,因为聚类算法还识别了背景中的一些区域。