{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 10197, "status": "ok", "timestamp": 1733327907192, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "s5gldFUP1Ta9", "outputId": "0f3abd7a-48e9-4166-9d9f-9ee6ff65c32e" }, "outputs": [], "source": [ "import requests\n", "import json\n", "\n", "# Пример запроса к TCIA API, предполагающий JSON формат\n", "url = \"https://services.cancerimagingarchive.net/services/v3/TCIA/query/getSeries?Collection=TCGA-BRCA&format=json\"\n", "response = requests.get(url)\n", "\n", "# Проверка ответа\n", "if response.status_code == 200:\n", " print(\"Данные получены успешно\")\n", "\n", " # Преобразование ответа в JSON\n", " try:\n", " data = response.json()\n", " if data:\n", " print(json.dumps(data, indent=4)) # Печать данных в формате JSON с отступами\n", "\n", " # Обработка данных\n", " for item in data:\n", " series_instance_uid = item.get('SeriesInstanceUID', 'N/A')\n", " modality = item.get('Modality', 'N/A')\n", " protocol_name = item.get('ProtocolName', 'N/A')\n", " body_part_examined = item.get('BodyPartExamined', 'N/A')\n", "\n", " # Печать извлеченной информации\n", " print(f\"SeriesInstanceUID: {series_instance_uid}\")\n", " print(f\"Modality: {modality}\")\n", " print(f\"ProtocolName: {protocol_name}\")\n", " print(f\"BodyPartExamined: {body_part_examined}\")\n", " print('-' * 30)\n", " else:\n", " print(\"Нет данных для отображения.\")\n", " except json.JSONDecodeError:\n", " print(\"Ошибка преобразования ответа в JSON.\")\n", "else:\n", " print(f\"Ошибка получения данных. Статус код: {response.status_code}\")\n" ] }, { "cell_type": "markdown", "metadata": { "id": "1EMLEteH2PP8" }, "source": [ "получение изображений" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 8511, "status": "ok", "timestamp": 1733327923136, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "_jqz40802ScS", "outputId": "f36da207-d5e2-4753-ca64-3c38c52bbc61" }, "outputs": [], "source": [ "import os\n", "import requests\n", "\n", "# Пример использования SeriesInstanceUID\n", "series_instance_uid = \"1.3.6.1.4.1.14519.5.2.1.6450.4002.265963154110062013582166845425\" # Пример идентификатора\n", "\n", "# URL для загрузки изображений\n", "url = f\"https://services.cancerimagingarchive.net/services/v3/TCIA/query/getImage?SeriesInstanceUID={series_instance_uid}\"\n", "response = requests.get(url, stream=True)\n", "\n", "# Путь для сохранения ZIP-файла\n", "output_path = \"/content/images.zip\"\n", "\n", "# Создание необходимых папок, если их нет\n", "folder_path = os.path.dirname(output_path)\n", "os.makedirs(folder_path, exist_ok=True)\n", "\n", "# Проверка ответа и сохранение изображения\n", "if response.status_code == 200:\n", " print(f\"Сохранение файла в {output_path}\")\n", " with open(output_path, \"wb\") as file:\n", " for chunk in response.iter_content(chunk_size=128):\n", " file.write(chunk)\n", " print(f\"Изображения успешно загружены и сохранены как {output_path}\")\n", "else:\n", " print(\"Ошибка при загрузке изображений\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 487, "status": "ok", "timestamp": 1733327927800, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "5T9WU8e32ZwO", "outputId": "8607816e-7b09-45e6-f2ee-028195091358" }, "outputs": [], "source": [ "import zipfile\n", "\n", "# Распаковка загруженного ZIP-файла\n", "with zipfile.ZipFile(\"images.zip\", 'r') as zip_ref:\n", " zip_ref.extractall(\"images\") # Папка для распакованных изображений\n", "print(\"Файлы успешно распакованы\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 9944, "status": "ok", "timestamp": 1733327954427, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "wDnQciCD2nK7", "outputId": "114de64d-1dad-4e0f-fc25-6eb2f6f2be3c" }, "outputs": [], "source": [ "!pip install pydicom" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 5672, "status": "ok", "timestamp": 1733327939856, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "fy7iue6r-qLe", "outputId": "90f7405d-77ba-42cb-bcd1-daba88d8e46b" }, "outputs": [], "source": [ "pip install scikit-image" ] }, { "cell_type": "markdown", "metadata": { "id": "mHUiH_ra73lm" }, "source": [ "Вывод 20 случайных изображений серии" ] }, { "cell_type": "markdown", "metadata": { "id": "XLX5F2QA73ku" }, "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000, "output_embedded_package_id": "1bVzJQoS5a20xhtxUvdmWXcv0JVIyOj1_" }, "executionInfo": { "elapsed": 6961, "status": "ok", "timestamp": 1733161002828, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "ZG1Ab2X-3b3W", "outputId": "c8912e6e-d792-4147-ef1b-767e8c181ae3" }, "outputs": [], "source": [ "import os\n", "import random\n", "import pydicom\n", "import matplotlib.pyplot as plt\n", "\n", "# Папка с распакованными изображениями\n", "dicom_folder = \"images\"\n", "\n", "# Сбор всех DICOM-файлов в папке\n", "dicom_files = [os.path.join(dicom_folder, filename) for filename in os.listdir(dicom_folder) if filename.endswith(\".dcm\")]\n", "\n", "# Проверка, что в папке достаточно файлов для выбора 20\n", "num_files_to_show = min(20, len(dicom_files))\n", "\n", "# Выбор случайных файлов из списка случайным образом\n", "random_files = random.sample(dicom_files, num_files_to_show)\n", "\n", "# Визуализация выбранных изображений\n", "for dicom_path in random_files:\n", " dicom_data = pydicom.dcmread(dicom_path)\n", "\n", " # Получение массива пикселей изображения\n", " image = dicom_data.pixel_array\n", "\n", " # Визуализация изображения\n", " filename = os.path.basename(dicom_path)\n", " plt.imshow(image, cmap=\"gray\")\n", " plt.title(f\"Файл: {filename}\\nПациент ID: {dicom_data.PatientID}\")\n", " plt.axis(\"off\")\n", " plt.show()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "S33pbEOx3b2k" }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "id": "2tugza_l6CgF" }, "source": [ "После выбора изображениq, применим к нему обработку" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 878 }, "executionInfo": { "elapsed": 23682, "status": "ok", "timestamp": 1733136739686, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "u0rx2vLS6oYm", "outputId": "41fee910-4786-4c12-eeea-3a7b55ba6282" }, "outputs": [], "source": [ "import os\n", "import random\n", "import pydicom\n", "import matplotlib.pyplot as plt\n", "import cv2\n", "import numpy as np\n", "import skimage.restoration as restoration\n", "\n", "# Папка с распакованными изображениями\n", "dicom_folder = \"images\"\n", "\n", "# Сбор всех DICOM-файлов в папке\n", "dicom_files = [filename for filename in os.listdir(dicom_folder) if filename.endswith(\".dcm\")]\n", "\n", "# Запрос у пользователя названий файлов для отображения\n", "file_names = input(\"Введите названия файлов изображений через запятую: \").split(\",\")\n", "file_names = [name.strip() for name in file_names]\n", "\n", "# Поиск указанных файлов в папке\n", "selected_files = []\n", "for filename in file_names:\n", " found_files = [os.path.join(dicom_folder, f) for f in dicom_files if filename in f]\n", " selected_files.extend(found_files)\n", "\n", "# Визуализация выбранных изображений\n", "for dicom_path in selected_files:\n", " if os.path.exists(dicom_path):\n", " dicom_data = pydicom.dcmread(dicom_path)\n", "\n", " # Получение массива пикселей изображения\n", " image = dicom_data.pixel_array\n", "\n", " # Визуализация изображения\n", " filename = os.path.basename(dicom_path)\n", " plt.imshow(image, cmap=\"gray\")\n", " plt.title(f\"Файл: {filename}\\nПациент ID: {dicom_data.PatientID}\")\n", " plt.axis(\"off\")\n", " plt.show()\n", "\n", "# Применение адаптивного медианного фильтра для улучшения качества изображений перед сегментацией\n", "for dicom_path in selected_files:\n", " if os.path.exists(dicom_path):\n", " dicom_data = pydicom.dcmread(dicom_path)\n", " image = dicom_data.pixel_array\n", "\n", " # Преобразование изображения в формат uint8, если это необходимо\n", " if image.dtype != np.uint8:\n", " image = cv2.normalize(image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)\n", "\n", " # Применение адаптивного медианного фильтра для сглаживания шума\n", " filtered_image = restoration.denoise_bilateral(image, sigma_color=0.01, sigma_spatial=11, channel_axis=None)\n", "\n", " # Преобразование фильтрованного изображения обратно в формат uint8\n", " filtered_image = (filtered_image * 255).astype(np.uint8)\n", "\n", " # Визуализация фильтрованного изображения\n", " filename = os.path.basename(dicom_path)\n", " plt.imshow(filtered_image, cmap=\"gray\")\n", " plt.title(f\"Фильтрованное изображение: {filename}\")\n", " plt.axis(\"off\")\n", " plt.show()" ] }, { "cell_type": "markdown", "metadata": { "id": "LzHtNa0oAWzx" }, "source": [ "**watershed**" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "executionInfo": { "elapsed": 23251, "status": "ok", "timestamp": 1733161357153, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "_W5paV7yAaKX", "outputId": "f9eb183c-24a7-4187-a8ab-7e82f1072fd9" }, "outputs": [], "source": [ "import os\n", "import random\n", "import pydicom\n", "import matplotlib.pyplot as plt\n", "import cv2\n", "import numpy as np\n", "import skimage.restoration as restoration\n", "\n", "# Папка с распакованными изображениями\n", "dicom_folder = \"images\"\n", "\n", "# Сбор всех DICOM-файлов в папке\n", "dicom_files = [filename for filename in os.listdir(dicom_folder) if filename.endswith(\".dcm\")]\n", "\n", "# Запрос у пользователя названий файлов для отображения\n", "file_names = input(\"Введите названия файлов изображений через запятую: \").split(\",\")\n", "file_names = [name.strip() for name in file_names]\n", "\n", "# Поиск указанных файлов в папке\n", "selected_files = []\n", "for filename in file_names:\n", " found_files = [os.path.join(dicom_folder, f) for f in dicom_files if filename in f]\n", " selected_files.extend(found_files)\n", "\n", "# Визуализация выбранных изображений\n", "for dicom_path in selected_files:\n", " if os.path.exists(dicom_path):\n", " dicom_data = pydicom.dcmread(dicom_path)\n", "\n", " # Получение массива пикселей изображения\n", " image = dicom_data.pixel_array\n", "\n", " # Обрезка верхней 1/3 изображения\n", " height = image.shape[0]\n", " cropped_image = image[height // 3:, :]\n", "\n", " # Применение адаптивного выравнивания гистограммы (CLAHE)\n", " clahe = cv2.createCLAHE(clipLimit=0.5, tileGridSize=(3, 3))\n", " cropped_image = clahe.apply(cropped_image.astype(np.uint8))\n", "\n", " # Визуализация обрезанного изображения\n", " filename = os.path.basename(dicom_path)\n", " plt.imshow(cropped_image, cmap=\"gray\")\n", " plt.title(f\"Обрезанное изображение: {filename}\\nПациент ID: {dicom_data.PatientID}\")\n", " plt.axis(\"off\")\n", " plt.show()\n", "\n", "# Применение адаптивного медианного фильтра для улучшения качества изображений перед сегментацией\n", "for dicom_path in selected_files:\n", " if os.path.exists(dicom_path):\n", " dicom_data = pydicom.dcmread(dicom_path)\n", " image = dicom_data.pixel_array\n", "\n", " # Обрезка верхней 1/3 изображения\n", " height = image.shape[0]\n", " cropped_image = image[height // 3:, :]\n", "\n", " # Преобразование изображения в формат uint8, если это необходимо\n", " if cropped_image.dtype != np.uint8:\n", " cropped_image = cv2.normalize(cropped_image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)\n", "\n", " # Применение адаптивного медианного фильтра для сглаживания шума\n", " filtered_image = restoration.denoise_bilateral(cropped_image, sigma_color=0.05, sigma_spatial=5, channel_axis=None)\n", "\n", " # Преобразование фильтрованного изображения обратно в формат uint8\n", " filtered_image = (filtered_image * 255).astype(np.uint8)\n", "\n", " # Применение алгоритма водораздела для сегментации изображения\n", " # Создание маски для водораздела\n", " _, binary_image = cv2.threshold(filtered_image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)\n", " distance_transform = cv2.distanceTransform(binary_image, cv2.DIST_L2, 5)\n", " _, sure_fg = cv2.threshold(distance_transform, 0.9 * distance_transform.max(), 255, 0)\n", " sure_fg = np.uint8(sure_fg)\n", " unknown = cv2.subtract(binary_image, sure_fg)\n", "\n", " # Маркировка объектов\n", " num_markers, markers = cv2.connectedComponents(sure_fg)\n", " markers = markers + 1\n", " markers[unknown == 255] = 0\n", "\n", " # Применение водораздела\n", " markers = cv2.watershed(cv2.cvtColor(filtered_image, cv2.COLOR_GRAY2BGR), markers)\n", " segmented_image = np.zeros_like(filtered_image)\n", " segmented_image[markers == -1] = 255\n", "\n", " # Наложение сегментированного изображения на исходное с зелеными границами\n", " original_image_bgr = cv2.cvtColor(cropped_image, cv2.COLOR_GRAY2BGR)\n", " original_image_bgr[markers == -1] = [0, 255, 0] # Установка зеленого цвета для границ\n", "\n", " # Визуализация наложенного изображения\n", " filename = os.path.basename(dicom_path)\n", " plt.imshow(cv2.cvtColor(original_image_bgr, cv2.COLOR_BGR2RGB))\n", " plt.title(f\"Сегментированное изображение с наложением (водораздел): {filename}\")\n", " plt.axis(\"off\")\n", " plt.show()\n" ] }, { "cell_type": "markdown", "metadata": { "id": "bbDf5ciOYHfS" }, "source": [ "thresholding" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "executionInfo": { "elapsed": 8619, "status": "ok", "timestamp": 1733161943856, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "7YbBnF0fYLNw", "outputId": "29ed2b7a-1627-456a-dd32-86d0c4b06538" }, "outputs": [], "source": [ "import os\n", "import random\n", "import pydicom\n", "import matplotlib.pyplot as plt\n", "import cv2\n", "import numpy as np\n", "\n", "# Папка с распакованными изображениями\n", "dicom_folder = \"images\"\n", "\n", "# Сбор всех DICOM-файлов в папке\n", "dicom_files = [filename for filename in os.listdir(dicom_folder) if filename.endswith(\".dcm\")]\n", "\n", "# Запрос у пользователя названий файлов для отображения\n", "file_names = input(\"Введите названия файлов изображений через запятую: \").split(\",\")\n", "file_names = [name.strip() for name in file_names]\n", "\n", "# Поиск указанных файлов в папке\n", "selected_files = []\n", "for filename in file_names:\n", " found_files = [os.path.join(dicom_folder, f) for f in dicom_files if filename in f]\n", " selected_files.extend(found_files)\n", "\n", "# Визуализация выбранных изображений\n", "for dicom_path in selected_files:\n", " if os.path.exists(dicom_path):\n", " dicom_data = pydicom.dcmread(dicom_path)\n", "\n", " # Получение массива пикселей изображения\n", " image = dicom_data.pixel_array\n", "\n", " # Визуализация изображения\n", " filename = os.path.basename(dicom_path)\n", " plt.imshow(image, cmap=\"gray\")\n", " plt.title(f\"Файл: {filename}\\nПациент ID: {dicom_data.PatientID}\")\n", " plt.axis(\"off\")\n", " plt.show()\n", "\n", "# Применение обработки изображений перед сегментацией\n", "for dicom_path in selected_files:\n", " if os.path.exists(dicom_path):\n", " dicom_data = pydicom.dcmread(dicom_path)\n", " image = dicom_data.pixel_array\n", "\n", " # Обрезка верхней трети изображения\n", " height, width = image.shape\n", " cropped_image = image[height // 3: , :]\n", "\n", " # Преобразование изображения в формат uint8, если это необходимо\n", " if cropped_image.dtype != np.uint8:\n", " cropped_image = cv2.normalize(cropped_image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)\n", "\n", " # Применение адаптивного выравнивания гистограммы для повышения контрастности\n", " clahe = cv2.createCLAHE(clipLimit=1.5, tileGridSize=(8, 8))\n", " enhanced_image = clahe.apply(cropped_image)\n", "\n", " # Визуализация улучшенного изображения\n", " filename = os.path.basename(dicom_path)\n", " plt.imshow(enhanced_image, cmap=\"gray\")\n", " plt.title(f\"Улучшенное изображение: {filename}\")\n", " plt.axis(\"off\")\n", " plt.show()\n", "\n", " # Применение пороговой сегментации\n", " threshold_value = 100 # Порог можно изменять в зависимости от задачи\n", " _, thresholded_image = cv2.threshold(enhanced_image, threshold_value, 255, cv2.THRESH_BINARY)\n", "\n", " # Визуализация пороговой сегментации\n", " plt.imshow(thresholded_image, cmap=\"gray\")\n", " plt.title(f\"Пороговая сегментация: {filename}\")\n", " plt.axis(\"off\")\n", " plt.show()\n", "\n", " # Наложение сегментированного изображения на исходное с зеленой линией\n", " contours, _ = cv2.findContours(thresholded_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n", " overlay_image = cv2.cvtColor(cropped_image, cv2.COLOR_GRAY2BGR)\n", " cv2.drawContours(overlay_image, contours, -1, (0, 255, 0), 1)\n", "\n", " # Визуализация наложенного изображения\n", " plt.imshow(cv2.cvtColor(overlay_image, cv2.COLOR_BGR2RGB))\n", " plt.title(f\"Наложенное изображение: {filename}\")\n", " plt.axis(\"off\")\n", " plt.show()\n" ] }, { "cell_type": "markdown", "metadata": { "id": "F5PIzY6Y7fXU" }, "source": [ "FuzzyCmeans" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 3985, "status": "ok", "timestamp": 1733236827403, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "DPAimyHw8dSq", "outputId": "c8edd6bd-9fe7-4595-b7b6-2152cfeda19c" }, "outputs": [], "source": [ "pip install fuzzy-c-means" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "8RAcDcRi-ZlV" }, "outputs": [], "source": [ "pip install tabulate>=0.9.0" ] }, { "cell_type": "markdown", "metadata": { "id": "ak9OshsrOLrl" }, "source": [ "Обработка изображения - многослойная декомпозиция. Сегментация с Fuzzy C means" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "executionInfo": { "elapsed": 5336, "status": "ok", "timestamp": 1733162965578, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "IhGYJoriAXP_", "outputId": "0ac944eb-efe4-4516-e084-7a8adfccc256" }, "outputs": [], "source": [ "import cv2\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from scipy.special import expit\n", "from fcmeans import FCM # Для Fuzzy C-means\n", "\n", "# Загрузка изображения\n", "image_path = \"/content/8.png\" # Укажите путь к вашему изображению\n", "input_image = cv2.imread(image_path)\n", "if input_image is None:\n", " raise FileNotFoundError(f\"Не удалось загрузить изображение по указанному пути: {image_path}\")\n", "\n", "# Функция для отображения изображения\n", "def show_image(image, title):\n", " plt.figure(figsize=(10, 10))\n", " plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))\n", " plt.title(title)\n", " plt.axis('off')\n", " plt.show()\n", "\n", "# Функция для разложения изображения на базовый слой и детали\n", "def multiscale_decomposition(image, kernel_size=5):\n", " base_layer = cv2.GaussianBlur(image, (kernel_size, kernel_size), 0)\n", " detail_layer_1 = cv2.subtract(image, base_layer)\n", " detail_layer_2 = cv2.subtract(base_layer, cv2.GaussianBlur(base_layer, (kernel_size, kernel_size), 0))\n", " return base_layer, detail_layer_1, detail_layer_2\n", "\n", "# Функция для применения сигмоиды к каждому пикселю\n", "def sigmoid(x, a=1):\n", " return expit(a * x)\n", "\n", "# Функция для применения тонового улучшения на основе трехуровневой декомпозиции\n", "def multiscale_tone_enhancement(image, delta_0=1.1, delta_1=2.5, delta_2=2.2, alpha=0.5):\n", " # Разложение изображения на базовый слой и два слоя детализации\n", " base_layer, detail_layer_1, detail_layer_2 = multiscale_decomposition(image, kernel_size=5)\n", "\n", " # Среднее значение яркости для каждого канала\n", " mu = np.mean(base_layer, axis=(0, 1))\n", "\n", " # Применение S-симгмоиды для управления усилением деталей\n", " S = lambda x: sigmoid((x - mu) / 255.0, a=alpha)\n", "\n", " # Усиление базового слоя и слоев детализации\n", " enhanced_image = base_layer + delta_0 * (base_layer - mu) + \\\n", " 0.9 * S(detail_layer_1) * (delta_1 * detail_layer_1) + \\\n", " 0.9 * S(detail_layer_2) * (delta_2 * detail_layer_2)\n", "\n", " # Клиппинг результата в допустимый диапазон [0, 255]\n", " enhanced_image = np.clip(enhanced_image, 0, 255).astype(np.uint8)\n", " return enhanced_image\n", "\n", "# Применение тонового улучшения\n", "enhanced_image = multiscale_tone_enhancement(input_image)\n", "\n", "# Преобразование изображения в градации серого для FCM\n", "gray_image = cv2.cvtColor(enhanced_image, cv2.COLOR_BGR2GRAY)\n", "\n", "# Преобразование изображения в формат, подходящий для FCM\n", "reshaped_image = gray_image.flatten().astype(np.float64) / 255.0\n", "\n", "# Применение Fuzzy C-means\n", "num_clusters = 5 # Задайте количество кластеров\n", "fcm = FCM(n_clusters=num_clusters)\n", "fcm.fit(reshaped_image.reshape(-1, 1))\n", "cluster_labels = fcm.u.argmax(axis=1) # Метки кластеров\n", "\n", "# Преобразование кластеров в форму изображения\n", "segmented_image = cluster_labels.reshape(gray_image.shape)\n", "\n", "# Отображение результатов\n", "show_image(input_image, 'Original Image')\n", "show_image(enhanced_image, 'Enhanced Image')\n", "plt.figure(figsize=(10, 10))\n", "plt.imshow(segmented_image, cmap=\"jet\")\n", "plt.title(\"Fuzzy C-means Segmentation\")\n", "plt.axis('off')\n", "plt.show()\n" ] }, { "cell_type": "markdown", "metadata": { "id": "v30wSTf2z2KX" }, "source": [ "Метод активных контуров - змеек" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 3699, "status": "ok", "timestamp": 1733327984318, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "8w6lib4r14jZ", "outputId": "8e5c5470-d875-4f42-8d53-2751fb295d8e" }, "outputs": [], "source": [ "pip install scipy" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "executionInfo": { "elapsed": 5058, "status": "ok", "timestamp": 1733330809629, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "8JoBvPgwdlM1", "outputId": "1fa592ef-8270-4b25-c99f-2fe69110a350" }, "outputs": [], "source": [ "import os\n", "import matplotlib.pyplot as plt\n", "import cv2\n", "import numpy as np\n", "from skimage.segmentation import active_contour\n", "from scipy.spatial import distance\n", "\n", "# Функция для применения адаптивного медианного фильтра\n", "def adaptive_median_filter(image, max_kernel_size=5):\n", " filtered_image = image.copy()\n", " height, width = image.shape\n", "\n", " for i in range(height):\n", " for j in range(width):\n", " kernel_size = 3 # Начальный размер ядра\n", " while kernel_size <= max_kernel_size:\n", " # Получаем область с заданным размером ядра\n", " half_size = kernel_size // 2\n", " x_start = max(j - half_size, 0)\n", " x_end = min(j + half_size + 1, width)\n", " y_start = max(i - half_size, 0)\n", " y_end = min(i + half_size + 1, height)\n", "\n", " region = image[y_start:y_end, x_start:x_end]\n", " median_value = np.median(region)\n", "\n", " # Если медианное значение близко к текущему пикселю, увеличиваем размер ядра\n", " if abs(median_value - image[i, j]) < 10: # Порог можно настроить\n", " break\n", " kernel_size += 2 # Увеличиваем размер ядра, проверяя на большее\n", " filtered_image[i, j] = median_value\n", "\n", " return filtered_image\n", "\n", "# Функция для объединения пересекающихся контуров\n", "def merge_contours(contours, min_distance=10):\n", " merged_contours = []\n", "\n", " while contours:\n", " contour = contours.pop(0)\n", " merged = False\n", " for i, existing_contour in enumerate(merged_contours):\n", " # Проверяем, пересекаются ли контуры (минимальное расстояние между точками)\n", " if any(distance.euclidean(point, existing_point) < min_distance for point in contour for existing_point in existing_contour):\n", " # Если контуры пересекаются, объединяем их\n", " merged_contours[i] = np.vstack((existing_contour, contour))\n", " merged = True\n", " break\n", " if not merged:\n", " merged_contours.append(contour)\n", "\n", " return merged_contours\n", "\n", "# Загрузка изображения (например, PNG)\n", "image_path = \"/content/9.png\" # Укажите путь к вашему изображению\n", "input_image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)\n", "\n", "if input_image is None:\n", " raise FileNotFoundError(f\"Не удалось загрузить изображение по указанному пути: {image_path}\")\n", "\n", "# Обрезка верхней трети изображения (три восьмых сверху)\n", "cropped_image = input_image\n", "\n", "# Преобразование изображения в формат uint8, если это необходимо\n", "if cropped_image.dtype != np.uint8:\n", " cropped_image = cv2.normalize(cropped_image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)\n", "\n", "# Применение адаптивного медианного фильтра\n", "adaptive_filtered = adaptive_median_filter(cropped_image)\n", "\n", "# Визуализация результата CLAHE\n", "plt.figure(figsize=(6, 6))\n", "plt.imshow(adaptive_filtered, cmap=\"gray\")\n", "plt.axis(\"off\")\n", "plt.show()\n", "\n", "# Инвертирование изображения перед сегментацией\n", "inverted_image = np.invert(adaptive_filtered)\n", "\n", "# Применение пороговой сегментации для выделения светлых участков на инвертированном изображении\n", "gray_threshold = np.percentile(inverted_image, 90) # Порог для серых участков, 70-й перцентиль\n", "binary_image = inverted_image > gray_threshold # Выделяем светлые участки\n", "\n", "# Визуализация результата пороговой сегментации\n", "plt.figure(figsize=(6, 6))\n", "plt.imshow(binary_image, cmap=\"gray\")\n", "plt.title(\"Результат пороговой сегментации (светлые участки на инвертированном изображении)\")\n", "plt.axis(\"off\")\n", "plt.show()\n", "\n", "# Найдем контуры светлых областей на бинаризованном изображении\n", "contours, _ = cv2.findContours(binary_image.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n", "\n", "# Отсортируем контуры по площади и выберем 2 самых крупных\n", "contours = sorted(contours, key=cv2.contourArea, reverse=True)[:1] # Выбираем только 2 контуры\n", "\n", "# Генерация начальных точек для активных контуров\n", "init_points = []\n", "for contour in contours:\n", " # Найдем центры контуров\n", " M = cv2.moments(contour)\n", " if M['m00'] != 0:\n", " cx = int(M['m10'] / M['m00'])\n", " cy = int(M['m01'] / M['m00'])\n", " init_points.append((cy, cx))\n", "\n", "# Инициализация контуров с центрами\n", "init_contours = []\n", "for point in init_points:\n", " y, x = point\n", " s = np.linspace(0, 2 * np.pi, 400)\n", " r = y + 90 * np.sin(s)\n", " c = x + 90 * np.cos(s)\n", " init = np.array([r, c]).T\n", " init_contours.append(init)\n", "\n", "# Применение метода активных контуров\n", "fig, ax = plt.subplots()\n", "ax.imshow(inverted_image, cmap=\"gray\") # Выводим контуры на исходном изображении\n", "\n", "# Объединяем пересекающиеся контуры\n", "merged_contours = merge_contours(init_contours, min_distance=1)\n", "\n", "# Отображаем объединенные контуры\n", "for init in merged_contours:\n", " snake = active_contour(inverted_image, init, alpha=0.05, beta=0.1, gamma=0.001) # Параметры активного контура\n", " snake[:, 0] = np.clip(snake[:, 0], 0, inverted_image.shape[0] - 1) # ограничиваем по оси Y\n", " snake[:, 1] = np.clip(snake[:, 1], 0, inverted_image.shape[1] - 1) # ограничиваем по оси X\n", "\n", " # Проверяем, чтобы контуры не были в темных областях\n", " contour_values = inverted_image[tuple(snake.astype(int).T)]\n", "\n", " # Если средняя яркость вдоль контура больше порога, рисуем контур\n", " if np.mean(contour_values) >105: # Порог для яркости, можно настроить\n", " ax.plot(snake[:, 1], snake[:, 0], '-r', lw=2)\n", "\n", "ax.set_title(f\"Объединенные активные контуры: {os.path.basename(image_path)}\")\n", "ax.axis(\"off\")\n", "plt.show()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "background_save": true }, "id": "eKwxXTinna1u" }, "outputs": [], "source": [ "import os\n", "import pydicom\n", "import matplotlib.pyplot as plt\n", "import cv2\n", "import numpy as np\n", "from skimage.segmentation import active_contour\n", "from scipy.spatial import distance\n", "from skimage.morphology import disk\n", "\n", "# Папка с распакованными изображениями\n", "dicom_folder = \"images\"\n", "\n", "# Сбор всех DICOM-файлов в папке\n", "dicom_files = [filename for filename in os.listdir(dicom_folder) if filename.endswith(\".dcm\")]\n", "\n", "# Запрос у пользователя названий файлов для отображения\n", "file_names = input(\"Введите названия файлов изображений через запятую: \").split(\",\")\n", "file_names = [name.strip() for name in file_names]\n", "\n", "# Поиск указанных файлов в папке\n", "selected_files = []\n", "for filename in file_names:\n", " found_files = [os.path.join(dicom_folder, f) for f in dicom_files if filename in f]\n", " selected_files.extend(found_files)\n", "\n", "# Функция для применения адаптивного медианного фильтра\n", "def adaptive_median_filter(image, max_kernel_size=15):\n", " filtered_image = image.copy()\n", " height, width = image.shape\n", "\n", " for i in range(height):\n", " for j in range(width):\n", " kernel_size = 3 # Начальный размер ядра\n", " while kernel_size <= max_kernel_size:\n", " # Получаем область с заданным размером ядра\n", " half_size = kernel_size // 2\n", " x_start = max(j - half_size, 0)\n", " x_end = min(j + half_size + 1, width)\n", " y_start = max(i - half_size, 0)\n", " y_end = min(i + half_size + 1, height)\n", "\n", " region = image[y_start:y_end, x_start:x_end]\n", " median_value = np.median(region)\n", "\n", " # Если медианное значение близко к текущему пикселю, увеличиваем размер ядра\n", " if abs(median_value - image[i, j]) < 10: # Порог можно настроить\n", " break\n", " kernel_size += 2 # Увеличиваем размер ядра, проверяя на большее\n", " filtered_image[i, j] = median_value\n", "\n", " return filtered_image\n", "\n", "# Функция для объединения пересекающихся контуров\n", "def merge_contours(contours, min_distance=10):\n", " merged_contours = []\n", "\n", " while contours:\n", " contour = contours.pop(0)\n", " merged = False\n", " for i, existing_contour in enumerate(merged_contours):\n", " # Проверяем, пересекаются ли контуры (минимальное расстояние между точками)\n", " if any(distance.euclidean(point, existing_point) < min_distance for point in contour for existing_point in existing_contour):\n", " # Если контуры пересекаются, объединяем их\n", " merged_contours[i] = np.vstack((existing_contour, contour))\n", " merged = True\n", " break\n", " if not merged:\n", " merged_contours.append(contour)\n", "\n", " return merged_contours\n", "\n", "# Обработка каждого выбранного DICOM файла\n", "for dicom_path in selected_files:\n", " if os.path.exists(dicom_path):\n", " dicom_data = pydicom.dcmread(dicom_path)\n", " image = dicom_data.pixel_array\n", "\n", " # Обрезка верхней трети изображения (три восьмых сверху)\n", " height, width = image.shape\n", " cropped_image = image[int(height * 3 / 8):, :]\n", "\n", " # Преобразование изображения в формат uint8, если это необходимо\n", " if cropped_image.dtype != np.uint8:\n", " cropped_image = cv2.normalize(cropped_image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)\n", "\n", " # Применение фильтра для увеличения яркости (CLAHE)\n", " #clahe = cv2.createCLAHE(clipLimit=5.0, tileGridSize=(1, 1))\n", " enhanced_image = cropped_image\n", "\n", " # Визуализация результата CLAHE\n", " plt.figure(figsize=(6, 6))\n", " plt.imshow(enhanced_image, cmap=\"gray\")\n", " # plt.title(\"После CLAHE (выравнивание гистограммы)\")\n", " plt.axis(\"off\")\n", " plt.show()\n", "\n", " # Применение пороговой сегментации для выделения светлых участков\n", " gray_threshold = np.percentile(enhanced_image, 90) # Порог для серых участков, 75-й перцентиль\n", " binary_image = enhanced_image > gray_threshold # Выделяем светлые участки\n", "\n", " # Инвертируем бинарное изображение, чтобы контуры были на светлых областях\n", " # binary_image = np.invert(binary_image)\n", "\n", " # Визуализация результата пороговой сегментации\n", " plt.figure(figsize=(6, 6))\n", " plt.imshow(binary_image, cmap=\"gray\")\n", " plt.title(\"Результат пороговой сегментации (светлые участки)\")\n", " plt.axis(\"off\")\n", " plt.show()\n", "\n", " # Найдем контуры светлых областей\n", " contours, _ = cv2.findContours(binary_image.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n", "\n", " # Отсортируем контуры по площади и выберем 3 самых больших\n", " contours = sorted(contours, key=cv2.contourArea, reverse=True)[:2]\n", "\n", " # Генерация начальных точек для активных контуров\n", " init_points = []\n", " for contour in contours:\n", " # Найдем центры контуров\n", " M = cv2.moments(contour)\n", " if M['m00'] != 0:\n", " cx = int(M['m10'] / M['m00'])\n", " cy = int(M['m01'] / M['m00'])\n", " init_points.append((cy, cx))\n", "\n", " # Инициализация контуров с центрами\n", " init_contours = []\n", " for point in init_points:\n", " y, x = point\n", " s = np.linspace(0, 2 * np.pi, 400)\n", " r = y + 90 * np.sin(s)\n", " c = x + 90 * np.cos(s)\n", " init = np.array([r, c]).T\n", " init_contours.append(init)\n", "\n", " # Применение метода активных контуров\n", " fig, ax = plt.subplots()\n", " ax.imshow(enhanced_image, cmap=\"gray\")\n", "\n", " # Объединяем пересекающиеся контуры\n", " merged_contours = merge_contours(init_contours, min_distance=10)\n", "\n", " # Отображаем объединенные контуры\n", " for init in merged_contours:\n", " snake = active_contour(enhanced_image, init, alpha=0.1, beta=0.002, gamma=0.001)\n", " snake[:, 0] = np.clip(snake[:, 0], 0, enhanced_image.shape[0] - 1) # ограничиваем по оси Y\n", " snake[:, 1] = np.clip(snake[:, 1], 0, enhanced_image.shape[1] - 1) # ограничиваем по оси X\n", "\n", " # Теперь проверяем, чтобы контуры не были в темных областях\n", " contour_values = enhanced_image[tuple(snake.astype(int).T)]\n", "\n", " # Если средняя яркость вдоль контура меньше порога, не рисуем контур\n", " if np.mean(contour_values) > 0: # Порог для яркости, можно настроить\n", " ax.plot(snake[:, 1], snake[:, 0], '-r', lw=2)\n", "\n", " ax.set_title(f\"Объединенные активные контуры: {os.path.basename(dicom_path)}\")\n", " ax.axis(\"off\")\n", " plt.show()\n" ] }, { "cell_type": "markdown", "metadata": { "id": "5GL9iwgn-4pr" }, "source": [ "Графы\n", "Графическая визуализация" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "executionInfo": { "elapsed": 854, "status": "ok", "timestamp": 1733306605637, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "fN7ANg0jHxHX", "outputId": "88a89cb6-2da4-4ea2-c4e5-25f1f07e28f5" }, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import networkx as nx\n", "\n", "# Создаем простое изображение как матрицу интенсивностей\n", "image = np.array([\n", " [10, 10, 20, 20],\n", " [10, 10, 20, 20],\n", " [30, 30, 40, 40],\n", " [30, 30, 40, 40]\n", "])\n", "\n", "# Визуализируем изображение и матрицу интенсивностей\n", "fig, ax = plt.subplots(1, 2, figsize=(10, 5))\n", "ax[0].imshow(image, cmap='gray')\n", "ax[0].set_title('Исходное изображение')\n", "ax[0].axis('off')\n", "\n", "# Отображаем матрицу интенсивностей на втором графике\n", "for i in range(image.shape[0]):\n", " for j in range(image.shape[1]):\n", " ax[1].text(j, i, str(image[i, j]), ha='center', va='center', color='black')\n", "ax[1].imshow(image, cmap='gray', alpha=0.5)\n", "ax[1].set_title('Матрица интенсивностей')\n", "ax[1].axis('off')\n", "\n", "plt.show()\n", "\n", "# Создаем граф из изображения\n", "rows, cols = image.shape\n", "graph = nx.grid_2d_graph(rows, cols)\n", "\n", "# Добавляем веса ребрам графа на основе разницы интенсивностей\n", "for i in range(rows):\n", " for j in range(cols):\n", " if i < rows - 1:\n", " weight = np.abs(image[i, j] - image[i + 1, j])\n", " graph.add_edge((i, j), (i + 1, j), weight=weight)\n", " if j < cols - 1:\n", " weight = np.abs(image[i, j] - image[i, j + 1])\n", " graph.add_edge((i, j), (i, j + 1), weight=weight)\n", "\n", "# Визуализируем граф\n", "pos = {(i, j): (j, -i) for i, j in graph.nodes()}\n", "weights = [graph[u][v]['weight'] for u, v in graph.edges()]\n", "\n", "plt.figure(figsize=(8, 8))\n", "nx.draw(graph, pos, with_labels=True, node_size=500, font_size=8, width=weights, edge_color=weights, edge_cmap=plt.cm.Blues)\n", "plt.title('Графовое представление изображения')\n", "plt.show()\n", "\n", "# Простая сегментация на основе порога веса\n", "threshold = 15\n", "segments = []\n", "for component in nx.connected_components(graph):\n", " subgraph = graph.subgraph(component)\n", " if all(graph[u][v]['weight'] <= threshold for u, v in subgraph.edges()):\n", " segments.append(component)\n", "\n", "# Визуализируем сегменты\n", "segmented_image = np.zeros_like(image)\n", "for idx, segment in enumerate(segments, start=1):\n", " for (i, j) in segment:\n", " segmented_image[i, j] = 255 - (idx * 50)\n", "\n", "plt.figure(figsize=(5, 5))\n", "plt.imshow(segmented_image, cmap='gray')\n", "plt.title('Сегментированное изображение')\n", "plt.show()\n" ] }, { "cell_type": "markdown", "metadata": { "id": "KAHyPKy5I6Bi" }, "source": [ "Сегментация графовым методом минимального разреза" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 10, "status": "ok", "timestamp": 1733324307973, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "sc91Ebh4U63z", "outputId": "1da952f0-a375-4dec-e59e-7c61d8f6063a" }, "outputs": [], "source": [ "pip install pygraph\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 445 }, "executionInfo": { "elapsed": 15633, "status": "ok", "timestamp": 1733312122850, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "o5E7GVLNbUwn", "outputId": "a44d3093-4f09-44a2-b462-130d1a5c283c" }, "outputs": [], "source": [ "import os\n", "import pydicom\n", "import matplotlib.pyplot as plt\n", "import cv2\n", "import numpy as np\n", "import networkx as nx\n", "\n", "# Пример графовой сегментации (графовый минимум разреза)\n", "def graph_cut_segmentation(image, threshold=100, max_weight=100):\n", " # Преобразуем изображение в бинарное\n", " ret, binary_image = cv2.threshold(image, threshold, 255, cv2.THRESH_BINARY)\n", "\n", " # Получаем размеры изображения\n", " rows, cols = binary_image.shape\n", "\n", " # Создаем граф\n", " G = nx.grid_2d_graph(rows, cols)\n", "\n", " # Присваиваем веса рёбрам, которые отражают разницу в яркости пикселей\n", " for i in range(rows):\n", " for j in range(cols):\n", " if i < rows - 1: # Вертикальные рёбра\n", " weight = np.abs(int(binary_image[i, j]) - int(binary_image[i + 1, j]))\n", " weight = max(1, min(weight, max_weight)) # Ограничиваем минимальный вес на 1, максимальный на max_weight\n", " G.add_edge((i, j), (i + 1, j), weight=weight)\n", "\n", " if j < cols - 1: # Горизонтальные рёбра\n", " weight = np.abs(int(binary_image[i, j]) - int(binary_image[i, j + 1]))\n", " weight = max(1, min(weight, max_weight)) # Ограничиваем минимальный вес на 1, максимальный на max_weight\n", " G.add_edge((i, j), (i, j + 1), weight=weight)\n", "\n", " # Определяем источник и сток (например, верхний левый и нижний правый углы)\n", " source = (0, 0)\n", " sink = (rows - 1, cols - 1)\n", "\n", " try:\n", " # Выполняем минимальный разрез\n", " cut_value, partition = nx.minimum_cut(G, source, sink)\n", " reachable, non_reachable = partition\n", "\n", " # Сегментированное изображение\n", " segmented_image = np.zeros_like(binary_image)\n", "\n", " for (i, j) in reachable:\n", " segmented_image[i, j] = 255\n", "\n", " for (i, j) in non_reachable:\n", " segmented_image[i, j] = 0\n", "\n", " return segmented_image\n", "\n", " except nx.NetworkXUnbounded:\n", " print(\"Ошибка: Найден путь с бесконечной пропускной способностью. Проверьте веса рёбер.\")\n", " return None\n", "\n", "\n", "# Папка с распакованными изображениями\n", "dicom_folder = \"images\"\n", "\n", "# Сбор всех DICOM-файлов в папке\n", "dicom_files = [filename for filename in os.listdir(dicom_folder) if filename.endswith(\".dcm\")]\n", "\n", "# Запрос у пользователя названий файлов для отображения\n", "file_names = input(\"Введите названия файлов изображений через запятую: \").split(\",\")\n", "file_names = [name.strip() for name in file_names]\n", "\n", "# Поиск указанных файлов в папке\n", "selected_files = []\n", "for filename in file_names:\n", " found_files = [os.path.join(dicom_folder, f) for f in dicom_files if filename in f]\n", " selected_files.extend(found_files)\n", "\n", "# Обработка и сегментация изображений\n", "for dicom_path in selected_files:\n", " if os.path.exists(dicom_path):\n", " dicom_data = pydicom.dcmread(dicom_path)\n", " image = dicom_data.pixel_array\n", "\n", " # Обрезка верхних 40% изображения (оставляем нижние 60%)\n", " height = image.shape[0]\n", " cropped_image = image[height // 3:, :] # Обрезаем верхнюю 40%\n", "\n", " # Проверка размера после обрезки\n", " print(f\"Размер обрезанного изображения: {cropped_image.shape}\")\n", "\n", " # Визуализация обрезанного изображения\n", " plt.imshow(cropped_image, cmap=\"gray\")\n", " plt.title(f\"Обрезанное изображение: {os.path.basename(dicom_path)}\")\n", " plt.axis(\"off\")\n", " plt.show()\n", "\n", " # Преобразование изображения в формат uint8, если это необходимо\n", " if cropped_image.dtype != np.uint8:\n", " cropped_image = cv2.normalize(cropped_image, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)\n", "\n", " # Применение адаптивного медианного фильтра для сглаживания шума\n", " filtered_image = cv2.fastNlMeansDenoising(cropped_image, None, 10, 7, 21)\n", "\n", " # Преобразование фильтрованного изображения обратно в формат uint8\n", " filtered_image = (filtered_image * 255).astype(np.uint8)\n", "\n", " # Применение графового метода сегментации\n", " segmented_image = graph_cut_segmentation(filtered_image, threshold=70, max_weight=50)\n", "\n", " # Если сегментация прошла успешно, выводим результат\n", " if segmented_image is not None:\n", " plt.imshow(segmented_image, cmap=\"gray\")\n", " plt.title(f\"Графовая сегментация (минимальный разрез): {os.path.basename(dicom_path)}\")\n", " plt.axis(\"off\")\n", " plt.show()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 6224, "status": "ok", "timestamp": 1733315226216, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "pGwk8fcqlD3r", "outputId": "b3708797-66c3-4e59-a308-1e4a88384f43" }, "outputs": [], "source": [ "!pip install cupy-cuda11x\n", "!pip install scikit-learn\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "executionInfo": { "elapsed": 1006, "status": "ok", "timestamp": 1733332484067, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "C74LMrzI8UqN", "outputId": "d3199a01-db0b-4b30-bca3-901671ffe662" }, "outputs": [], "source": [ "\n", "import cv2\n", "import matplotlib.pyplot as plt\n", "from skimage import segmentation, color\n", "import numpy as np\n", "\n", "# Путь к изображению на Google Диске\n", "image_path = '/content/7.png'\n", "\n", "# Загружаем изображение с помощью OpenCV\n", "image = cv2.imread(image_path)\n", "\n", "# OpenCV загружает изображение в формате BGR, но для отображения используем RGB\n", "image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n", "\n", "# Отображаем оригинальное изображение\n", "plt.imshow(image_rgb)\n", "plt.axis('off')\n", "plt.title('Original Image')\n", "plt.show()\n", "\n", "# Преобразуем изображение в формат для сегментации (float)\n", "image_float = np.float32(image_rgb) / 255.0\n", "\n", "# Применяем алгоритм Felzenszwalb-Huttenlocher для сегментации\n", "segments = segmentation.felzenszwalb(image_float, scale=500, sigma=0.05, min_size=50)\n", "\n", "# Отображаем результаты сегментации\n", "fig, ax = plt.subplots(1, 2, figsize=(12, 6))\n", "\n", "# Оригинальное изображение\n", "ax[0].imshow(image_rgb)\n", "ax[0].set_title('Original Image')\n", "ax[0].axis('off')\n", "\n", "# Сегментированное изображение\n", "ax[1].imshow(segments)\n", "ax[1].set_title('Segmented Image (Felzenszwalb-Huttenlocher)')\n", "ax[1].axis('off')\n", "\n", "plt.show()\n", "\n", "# Применяем цветовую карту для сегментации\n", "segmented_image = color.label2rgb(segments, image_rgb, kind='avg')\n", "\n", "# Отображаем цветную сегментацию\n", "plt.imshow(segmented_image)\n", "plt.title('Segmented Image with Colors')\n", "plt.axis('off')\n", "plt.show()\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "executionInfo": { "elapsed": 17015, "status": "ok", "timestamp": 1733324373410, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "T3cG-ndWKv5Y", "outputId": "383d61ee-48ff-45c6-fba8-a3e0bcc791be" }, "outputs": [], "source": [ "pip install scikit-learn" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 1000 }, "executionInfo": { "elapsed": 91492, "status": "ok", "timestamp": 1733332390246, "user": { "displayName": "E Shuvalova", "userId": "09074408506229732964" }, "user_tz": -180 }, "id": "UzQwZH60LtnN", "outputId": "2f4f9891-7041-4fe2-ef50-25716eca6724" }, "outputs": [], "source": [ "import cv2\n", "import matplotlib.pyplot as plt\n", "from skimage import segmentation, color\n", "import numpy as np\n", "from sklearn.cluster import SpectralClustering\n", "from skimage import img_as_float\n", "from sklearn.neighbors import kneighbors_graph\n", "\n", "# Путь к изображению на Google Диске\n", "image_path = '/content/7.png'\n", "\n", "# Загружаем изображение с помощью OpenCV\n", "image = cv2.imread(image_path)\n", "\n", "# OpenCV загружает изображение в формате BGR, но для отображения используем RGB\n", "image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n", "\n", "# Отображаем оригинальное изображение\n", "plt.imshow(image_rgb)\n", "plt.axis('off')\n", "plt.title('Original Image')\n", "plt.show()\n", "\n", "# Преобразуем изображение в формат для сегментации (float)\n", "image_float = np.float32(image_rgb) / 255.0\n", "\n", "# **Метод 1: Felzenszwalb-Huttenlocher**\n", "segments_fz = segmentation.felzenszwalb(image_float, scale=200, sigma=0.05, min_size=150)\n", "\n", "# **Метод 2: Graph Cut (Quickshift)**\n", "segments_quickshift = segmentation.quickshift(image_float, kernel_size=3, max_dist=6, ratio=0.9)\n", "\n", "# **Метод 3: Spectral Clustering**\n", "# Преобразуем изображение в граф с соседями\n", "image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n", "graph = kneighbors_graph(image_gray.reshape(-1, 1), n_neighbors=10, mode='distance', include_self=False)\n", "graph = 0.5 * (graph + graph.T) # Симметризация графа\n", "\n", "# Применяем спектральную кластеризацию\n", "sc = SpectralClustering(n_clusters=5, affinity='precomputed', n_init=10)\n", "segments_spectral = sc.fit_predict(graph.toarray()).reshape(image_gray.shape)\n", "\n", "# Отображаем результаты сегментации\n", "fig, ax = plt.subplots(1, 4, figsize=(16, 6))\n", "\n", "# Оригинальное изображение\n", "ax[0].imshow(image_rgb)\n", "ax[0].set_title('Original Image')\n", "ax[0].axis('off')\n", "\n", "# Felzenszwalb-Huttenlocher\n", "ax[1].imshow(segments_fz)\n", "ax[1].set_title('Felzenszwalb-Huttenlocher')\n", "ax[1].axis('off')\n", "\n", "# Graph Cut (Quickshift)\n", "ax[2].imshow(segments_quickshift)\n", "ax[2].set_title('Graph Cut (Quickshift)')\n", "ax[2].axis('off')\n", "\n", "# Spectral Clustering\n", "ax[3].imshow(segments_spectral)\n", "ax[3].set_title('Spectral Clustering')\n", "ax[3].axis('off')\n", "\n", "plt.tight_layout()\n", "plt.show()\n", "\n", "# Применяем цветовую карту для сегментации\n", "segmented_image_fz = color.label2rgb(segments_fz, image_rgb, kind='avg')\n", "segmented_image_quickshift = color.label2rgb(segments_quickshift, image_rgb, kind='avg')\n", "segmented_image_spectral = color.label2rgb(segments_spectral, image_rgb, kind='avg')\n", "\n", "# Отображаем цветные сегментации\n", "fig, ax = plt.subplots(1, 3, figsize=(18, 6))\n", "\n", "# Felzenszwalb-Huttenlocher\n", "ax[0].imshow(segmented_image_fz)\n", "ax[0].set_title('Segmented Image (Felzenszwalb-Huttenlocher)')\n", "ax[0].axis('off')\n", "\n", "# Graph Cut (Quickshift)\n", "ax[1].imshow(segmented_image_quickshift)\n", "ax[1].set_title('Segmented Image (Graph Cut - Quickshift)')\n", "ax[1].axis('off')\n", "\n", "# Spectral Clustering\n", "ax[2].imshow(segmented_image_spectral)\n", "ax[2].set_title('Segmented Image (Spectral Clustering)')\n", "ax[2].axis('off')\n", "\n", "plt.tight_layout()\n", "plt.show()\n" ] } ], "metadata": { "colab": { "authorship_tag": "ABX9TyNqotXgUNNGNY+IQjZNQBRs", "name": "", "version": "" }, "kernelspec": { "display_name": "Python 3", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 0 }