Примечание
Перейти в конец чтобы скачать полный пример кода или запустить этот пример в браузере через 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.401 секунд)
Связанные примеры
Сегментация изображения греческих монет на регионы
Компрессионное зондирование: реконструкция томографии с априорным распределением L1 (Lasso)
Удаление шума с изображения с использованием ядерного PCA