Добавлены итоговые блокноты, внешнее изображение

This commit is contained in:
Вера Виноградова 2025-05-15 00:54:26 +03:00
parent a7003303f8
commit a7a54edebc
10 changed files with 734 additions and 581 deletions

View File

@ -0,0 +1,16 @@
Описание задачи
Цель: сегментировать изображение на несколько однородных регионов с использованием спектральной кластеризации .
Алгоритм:
Изображение преобразуется в граф
Применяется спектральная кластеризация
Результат отображается в виде контуров вокруг найденных регионов
Поддерживаемые методы присвоения меток:
'kmeans'
'discretize'
'cluster_qr'
Для установки зависимостей:
pip install -r requirements.txt

View File

@ -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
}

View File

@ -0,0 +1,6 @@
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@ -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

84
app.py
View File

@ -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()

BIN
coins.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

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

View File

@ -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"
)