Примечание
Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере с помощью JupyterLite или Binder.
Спектральная кластеризация для сегментации изображений
В этом примере создаётся изображение с соприкасающимися кругами, а для разделения кругов используется спектральная кластеризация.
В этих условиях подход спектральной кластеризации решает задачу, известную как «нормализованный разрез графа»: изображение рассматривается как граф связанных вокселей, а алгоритм спектральной кластеризации выбирает разрезы графа, определяющие области, минимизируя отношение градиента вдоль разреза к объёму области.
Поскольку алгоритм пытается сбалансировать объёмы (то есть размеры областей), при использовании кругов разного размера сегментация не удаётся.
Кроме того, поскольку интенсивность изображения и его градиент не содержат полезной информации, мы выбираем для спектральной кластеризации граф, лишь слабо учитывающий градиент. Это близко к разбиению графа на ячейки диаграммы Вороного.
Кроме того, мы используем маску объектов, чтобы ограничить граф их контурами. В этом примере нас интересует разделение объектов друг от друга, а не от фона.
# Authors: The scikit-learn developers # 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 # We use a mask that limits to the foreground: the problem that we are # interested in here is not separating the objects from the background, # but separating them one from the other. 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)
Применим убывающую функцию градиента, в результате чего получим сегментацию, близкую к разбиению на ячейки диаграммы Вороного.
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()

Общее время выполнения скрипта: (0 минут 0.222 секунды)
Связанные примеры
© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/cluster/plot_segmentation_toy.html