Добавлены итоговые блокноты, внешнее изображение
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
Описание задачи
|
||||||
|
Цель: сегментировать изображение на несколько однородных регионов с использованием спектральной кластеризации .
|
||||||
|
|
||||||
|
Алгоритм:
|
||||||
|
|
||||||
|
Изображение преобразуется в граф
|
||||||
|
Применяется спектральная кластеризация
|
||||||
|
Результат отображается в виде контуров вокруг найденных регионов
|
||||||
|
Поддерживаемые методы присвоения меток:
|
||||||
|
|
||||||
|
'kmeans'
|
||||||
|
'discretize'
|
||||||
|
'cluster_qr'
|
||||||
|
|
||||||
|
Для установки зависимостей:
|
||||||
|
pip install -r requirements.txt
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"Сегментация изображения методом спектральной кластеризации\n",
|
||||||
|
"Описание задачи\n",
|
||||||
|
"Цель: разделить изображение монет на несколько регионов, используя спектральную кластеризацию .\n",
|
||||||
|
"\n",
|
||||||
|
"Алгоритм:\n",
|
||||||
|
"\n",
|
||||||
|
"Изображение преобразуется в граф\n",
|
||||||
|
"Каждый пиксель — вершина графа\n",
|
||||||
|
"Рёбра между соседними пикселями строятся на основе разницы яркости\n",
|
||||||
|
"Применяется спектральная кластеризация для выделения регионов\n",
|
||||||
|
"Источник данных:\n",
|
||||||
|
"\n",
|
||||||
|
"Встроенное изображение coins() из библиотеки skimage"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"1. Импорт библиотек"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import time\n",
|
||||||
|
"import numpy as np\n",
|
||||||
|
"import matplotlib.pyplot as plt\n",
|
||||||
|
"from scipy.ndimage import gaussian_filter\n",
|
||||||
|
"from skimage.data import coins\n",
|
||||||
|
"from skimage.transform import rescale\n",
|
||||||
|
"\n",
|
||||||
|
"from sklearn.cluster import spectral_clustering\n",
|
||||||
|
"from sklearn.feature_extraction import image"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"2. Загрузка и подготовка изображения"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Загружаем изображение монет\n",
|
||||||
|
"orig_coins = coins()\n",
|
||||||
|
"\n",
|
||||||
|
"# Уменьшаем размер изображения для ускорения обработки\n",
|
||||||
|
"# Перед уменьшением применяем фильтр Гаусса, чтобы уменьшить артефакты\n",
|
||||||
|
"smoothened_coins = gaussian_filter(orig_coins, sigma=2)\n",
|
||||||
|
"rescaled_coins = rescale(smoothened_coins, 0.2, mode=\"reflect\", anti_aliasing=False)\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Форма исходного изображения:\", orig_coins.shape)\n",
|
||||||
|
"print(\"Форма после масштабирования:\", rescaled_coins.shape)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"3. Построение графа"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Преобразуем изображение в граф\n",
|
||||||
|
"graph = image.img_to_graph(rescaled_coins)\n",
|
||||||
|
"\n",
|
||||||
|
"# Уменьшаем веса рёбер экспоненциальной функцией\n",
|
||||||
|
"beta = 10\n",
|
||||||
|
"eps = 1e-6\n",
|
||||||
|
"graph.data = np.exp(-beta * graph.data / graph.data.std()) + eps\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"Граф построен\")"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"4. Спектральная кластеризация"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# Количество регионов\n",
|
||||||
|
"n_regions = 26\n",
|
||||||
|
"n_plus = 3 # дополнительные кластеры для лучшей сегментации\n",
|
||||||
|
"\n",
|
||||||
|
"# Выполняем кластеризацию тремя способами\n",
|
||||||
|
"for assign_labels in (\"kmeans\", \"discretize\", \"cluster_qr\"):\n",
|
||||||
|
" t0 = time.time()\n",
|
||||||
|
" \n",
|
||||||
|
" labels = spectral_clustering(\n",
|
||||||
|
" graph,\n",
|
||||||
|
" n_clusters=(n_regions + n_plus),\n",
|
||||||
|
" eigen_tol=1e-7,\n",
|
||||||
|
" assign_labels=assign_labels,\n",
|
||||||
|
" random_state=42,\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" t1 = time.time()\n",
|
||||||
|
" labels = labels.reshape(rescaled_coins.shape)\n",
|
||||||
|
"\n",
|
||||||
|
" plt.figure(figsize=(5, 5))\n",
|
||||||
|
" plt.imshow(rescaled_coins, cmap=plt.cm.gray)\n",
|
||||||
|
" plt.xticks(())\n",
|
||||||
|
" plt.yticks(())\n",
|
||||||
|
"\n",
|
||||||
|
" title = f\"Спектральная кластеризация: {assign_labels}, {t1 - t0:.2f}с\"\n",
|
||||||
|
" print(title)\n",
|
||||||
|
" plt.title(title)\n",
|
||||||
|
"\n",
|
||||||
|
" for l in range(n_regions):\n",
|
||||||
|
" colors = [plt.cm.nipy_spectral((l + 4) / float(n_regions + 4))]\n",
|
||||||
|
" plt.contour(labels == l, colors=colors)\n",
|
||||||
|
"\n",
|
||||||
|
"plt.show()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"5. Интерпретация результатов\n",
|
||||||
|
"Каждое изображение показывает контуры найденных регионов. Цвета используются только для наглядности и не имеют семантической нагрузки.\n",
|
||||||
|
"\n",
|
||||||
|
"Методы:\n",
|
||||||
|
"\n",
|
||||||
|
"'kmeans' — стабильный, но может быть медленным\n",
|
||||||
|
"'discretize' — итеративный метод, работает быстрее\n",
|
||||||
|
"'cluster_qr' — новый экспериментальный метод, основанный на QR-разложении"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "Python 3 (ipykernel)",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.12.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 4
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"cells": [],
|
||||||
|
"metadata": {},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
@@ -1 +1,16 @@
|
|||||||
https://www.kaggle.com/datasets/sachinpatel21/az-handwritten-alphabets-in-csv-format/data
|
##Описание задачи
|
||||||
|
Цель: сегментировать изображение на несколько однородных регионов с использованием спектральной кластеризации .
|
||||||
|
|
||||||
|
#Алгоритм:
|
||||||
|
|
||||||
|
Изображение преобразуется в граф
|
||||||
|
Применяется спектральная кластеризация
|
||||||
|
Результат отображается в виде контуров вокруг найденных регионов
|
||||||
|
Поддерживаемые методы присвоения меток:
|
||||||
|
|
||||||
|
'kmeans'
|
||||||
|
'discretize'
|
||||||
|
'cluster_qr'
|
||||||
|
|
||||||
|
Для установки зависимостей:
|
||||||
|
pip install -r requirements.txt
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
import pandas as pd
|
|
||||||
import numpy as np
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
from sklearn.model_selection import train_test_split
|
|
||||||
from sklearn.svm import SVC
|
|
||||||
from sklearn.metrics import classification_report, ConfusionMatrixDisplay
|
|
||||||
|
|
||||||
# -----------------------------
|
|
||||||
# 1. Загрузка данных
|
|
||||||
# -----------------------------
|
|
||||||
# Попробуем определить, есть ли заголовки
|
|
||||||
try:
|
|
||||||
df = pd.read_csv('A_Z_HandwrittenLetters.csv')
|
|
||||||
if 'label' in df.columns:
|
|
||||||
print("Заголовки найдены, используется столбец 'label'")
|
|
||||||
else:
|
|
||||||
raise Exception("Столбец 'label' не найден")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Ошибка: {e}, попытка чтения без заголовков")
|
|
||||||
df = pd.read_csv('A_Z_HandwrittenLetters.csv', header=None)
|
|
||||||
|
|
||||||
# Разделение на признаки и метки
|
|
||||||
if 'label' in df.columns:
|
|
||||||
y = df['label'].values
|
|
||||||
X = df.drop('label', axis=1).values
|
|
||||||
else:
|
|
||||||
y = df[0].values
|
|
||||||
X = df.drop(0, axis=1).values
|
|
||||||
|
|
||||||
# -----------------------------
|
|
||||||
# 2. Нормализация
|
|
||||||
# -----------------------------
|
|
||||||
X = X / 255.0
|
|
||||||
|
|
||||||
# -----------------------------
|
|
||||||
# 3. Визуализация первых изображений
|
|
||||||
# -----------------------------
|
|
||||||
_, axes = plt.subplots(1, 4, figsize=(10, 5))
|
|
||||||
for ax, image, label in zip(axes, X[:4], y[:4]):
|
|
||||||
ax.imshow(image.reshape(28, 28), cmap='gray')
|
|
||||||
ax.axis('off')
|
|
||||||
ax.set_title(f"Label: {label}\n({chr(label + ord('A'))})")
|
|
||||||
plt.suptitle("Sample Training Images")
|
|
||||||
plt.show()
|
|
||||||
|
|
||||||
# -----------------------------
|
|
||||||
# 4. Разделение выборки
|
|
||||||
# -----------------------------
|
|
||||||
X_train, X_test, y_train, y_test = train_test_split(
|
|
||||||
X, y, test_size=0.3, random_state=42, shuffle=True
|
|
||||||
)
|
|
||||||
|
|
||||||
# -----------------------------
|
|
||||||
# 5. Обучение модели
|
|
||||||
# -----------------------------
|
|
||||||
print("Обучение модели...")
|
|
||||||
clf = SVC(gamma=0.001)
|
|
||||||
clf.fit(X_train, y_train)
|
|
||||||
|
|
||||||
# -----------------------------
|
|
||||||
# 6. Предсказание
|
|
||||||
# -----------------------------
|
|
||||||
y_pred = clf.predict(X_test)
|
|
||||||
|
|
||||||
# -----------------------------
|
|
||||||
# 7. Визуализация предсказаний
|
|
||||||
# -----------------------------
|
|
||||||
_, axes = plt.subplots(1, 4, figsize=(10, 5))
|
|
||||||
for ax, image, prediction in zip(axes, X_test, y_pred):
|
|
||||||
ax.imshow(image.reshape(28, 28), cmap='gray')
|
|
||||||
ax.axis('off')
|
|
||||||
ax.set_title(f"Prediction: {prediction}\n({chr(prediction + ord('A'))})")
|
|
||||||
plt.suptitle("Predicted Letters")
|
|
||||||
plt.show()
|
|
||||||
|
|
||||||
# -----------------------------
|
|
||||||
# 8. Отчеты и матрица ошибок
|
|
||||||
# -----------------------------
|
|
||||||
print("\nClassification Report:")
|
|
||||||
print(classification_report(y_test, y_pred))
|
|
||||||
|
|
||||||
disp = ConfusionMatrixDisplay.from_predictions(y_test, y_pred)
|
|
||||||
disp.figure_.suptitle("Confusion Matrix")
|
|
||||||
plt.show()
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,128 +0,0 @@
|
|||||||
"""
|
|
||||||
================================
|
|
||||||
Recognizing hand-written digits
|
|
||||||
================================
|
|
||||||
|
|
||||||
This example shows how scikit-learn can be used to recognize images of
|
|
||||||
hand-written digits, from 0-9.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Authors: The scikit-learn developers
|
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
# Standard scientific Python imports
|
|
||||||
import matplotlib.pyplot as plt
|
|
||||||
|
|
||||||
# Import datasets, classifiers and performance metrics
|
|
||||||
from sklearn import datasets, metrics, svm
|
|
||||||
from sklearn.model_selection import train_test_split
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Digits dataset
|
|
||||||
# --------------
|
|
||||||
#
|
|
||||||
# The digits dataset consists of 8x8
|
|
||||||
# pixel images of digits. The ``images`` attribute of the dataset stores
|
|
||||||
# 8x8 arrays of grayscale values for each image. We will use these arrays to
|
|
||||||
# visualize the first 4 images. The ``target`` attribute of the dataset stores
|
|
||||||
# the digit each image represents and this is included in the title of the 4
|
|
||||||
# plots below.
|
|
||||||
#
|
|
||||||
# Note: if we were working from image files (e.g., 'png' files), we would load
|
|
||||||
# them using :func:`matplotlib.pyplot.imread`.
|
|
||||||
|
|
||||||
digits = datasets.load_digits()
|
|
||||||
|
|
||||||
_, axes = plt.subplots(nrows=1, ncols=4, figsize=(10, 3))
|
|
||||||
for ax, image, label in zip(axes, digits.images, digits.target):
|
|
||||||
ax.set_axis_off()
|
|
||||||
ax.imshow(image, cmap=plt.cm.gray_r, interpolation="nearest")
|
|
||||||
ax.set_title("Training: %i" % label)
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Classification
|
|
||||||
# --------------
|
|
||||||
#
|
|
||||||
# To apply a classifier on this data, we need to flatten the images, turning
|
|
||||||
# each 2-D array of grayscale values from shape ``(8, 8)`` into shape
|
|
||||||
# ``(64,)``. Subsequently, the entire dataset will be of shape
|
|
||||||
# ``(n_samples, n_features)``, where ``n_samples`` is the number of images and
|
|
||||||
# ``n_features`` is the total number of pixels in each image.
|
|
||||||
#
|
|
||||||
# We can then split the data into train and test subsets and fit a support
|
|
||||||
# vector classifier on the train samples. The fitted classifier can
|
|
||||||
# subsequently be used to predict the value of the digit for the samples
|
|
||||||
# in the test subset.
|
|
||||||
|
|
||||||
# flatten the images
|
|
||||||
n_samples = len(digits.images)
|
|
||||||
data = digits.images.reshape((n_samples, -1))
|
|
||||||
|
|
||||||
# Create a classifier: a support vector classifier
|
|
||||||
clf = svm.SVC(gamma=0.001)
|
|
||||||
|
|
||||||
# Split data into 50% train and 50% test subsets
|
|
||||||
X_train, X_test, y_train, y_test = train_test_split(
|
|
||||||
data, digits.target, test_size=0.5, shuffle=False
|
|
||||||
)
|
|
||||||
|
|
||||||
# Learn the digits on the train subset
|
|
||||||
clf.fit(X_train, y_train)
|
|
||||||
|
|
||||||
# Predict the value of the digit on the test subset
|
|
||||||
predicted = clf.predict(X_test)
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Below we visualize the first 4 test samples and show their predicted
|
|
||||||
# digit value in the title.
|
|
||||||
|
|
||||||
_, axes = plt.subplots(nrows=1, ncols=4, figsize=(10, 3))
|
|
||||||
for ax, image, prediction in zip(axes, X_test, predicted):
|
|
||||||
ax.set_axis_off()
|
|
||||||
image = image.reshape(8, 8)
|
|
||||||
ax.imshow(image, cmap=plt.cm.gray_r, interpolation="nearest")
|
|
||||||
ax.set_title(f"Prediction: {prediction}")
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# :func:`~sklearn.metrics.classification_report` builds a text report showing
|
|
||||||
# the main classification metrics.
|
|
||||||
|
|
||||||
print(
|
|
||||||
f"Classification report for classifier {clf}:\n"
|
|
||||||
f"{metrics.classification_report(y_test, predicted)}\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# We can also plot a :ref:`confusion matrix <confusion_matrix>` of the
|
|
||||||
# true digit values and the predicted digit values.
|
|
||||||
|
|
||||||
disp = metrics.ConfusionMatrixDisplay.from_predictions(y_test, predicted)
|
|
||||||
disp.figure_.suptitle("Confusion Matrix")
|
|
||||||
print(f"Confusion matrix:\n{disp.confusion_matrix}")
|
|
||||||
|
|
||||||
plt.show()
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# If the results from evaluating a classifier are stored in the form of a
|
|
||||||
# :ref:`confusion matrix <confusion_matrix>` and not in terms of `y_true` and
|
|
||||||
# `y_pred`, one can still build a :func:`~sklearn.metrics.classification_report`
|
|
||||||
# as follows:
|
|
||||||
|
|
||||||
|
|
||||||
# The ground truth and predicted lists
|
|
||||||
y_true = []
|
|
||||||
y_pred = []
|
|
||||||
cm = disp.confusion_matrix
|
|
||||||
|
|
||||||
# For each cell in the confusion matrix, add the corresponding ground truths
|
|
||||||
# and predictions to the lists
|
|
||||||
for gt in range(len(cm)):
|
|
||||||
for pred in range(len(cm)):
|
|
||||||
y_true += [gt] * cm[gt][pred]
|
|
||||||
y_pred += [pred] * cm[gt][pred]
|
|
||||||
|
|
||||||
print(
|
|
||||||
"Classification report rebuilt from confusion matrix:\n"
|
|
||||||
f"{metrics.classification_report(y_true, y_pred)}\n"
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user