Initial commit: project structure, scripts and documentation
This commit is contained in:
LFS
BIN
Binary file not shown.
+975
@@ -0,0 +1,975 @@
|
||||
% ============================================================================
|
||||
% ЛАБОРАТОРНАЯ РАБОТА №1
|
||||
% АУДИТ И ПОДГОТОВКА МЕДИЦИНСКИХ ДАННЫХ
|
||||
% ============================================================================
|
||||
% КОМПИЛЯЦИЯ: pdflatex (ДВА ПРОХОДА)
|
||||
% ============================================================================
|
||||
|
||||
\documentclass[12pt,a4paper]{article}
|
||||
|
||||
% ============================================================================
|
||||
% ПРЕАМБУЛА
|
||||
% ============================================================================
|
||||
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T2A]{fontenc}
|
||||
\usepackage[russian]{babel}
|
||||
|
||||
\usepackage{amsmath,amssymb,amsfonts}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{listings}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{geometry}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{longtable}
|
||||
\usepackage{caption}
|
||||
\usepackage{subcaption}
|
||||
\usepackage{titlesec}
|
||||
\usepackage{float}
|
||||
\usepackage{array}
|
||||
\usepackage{multirow}
|
||||
\usepackage{enumitem}
|
||||
|
||||
\geometry{left=2.5cm,right=2cm,top=2cm,bottom=2cm}
|
||||
|
||||
% --- Гиперссылки ---
|
||||
\hypersetup{
|
||||
colorlinks=true,
|
||||
linkcolor=blue,
|
||||
urlcolor=blue,
|
||||
pdfauthor={Студент},
|
||||
pdftitle={Лабораторная работа N1}
|
||||
}
|
||||
|
||||
% --- Листинги (максимально упрощённые) ---
|
||||
\lstset{
|
||||
basicstyle=\ttfamily\footnotesize,
|
||||
keywordstyle=\color{blue},
|
||||
commentstyle=\color{green!60!black},
|
||||
stringstyle=\color{red},
|
||||
breaklines=true,
|
||||
frame=single,
|
||||
numbers=left,
|
||||
numberstyle=\tiny,
|
||||
tabsize=4,
|
||||
language=Python,
|
||||
extendedchars=true,
|
||||
inputencoding=utf8,
|
||||
}
|
||||
|
||||
% --- Заголовки ---
|
||||
\titleformat{\section}{\Large\bfseries\centering}{}{0pt}{}
|
||||
\titleformat{\subsection}{\large\bfseries}{}{0pt}{}
|
||||
\titleformat{\subsubsection}{\normalsize\bfseries}{}{0pt}{}
|
||||
|
||||
% --- Список литературы ---
|
||||
\renewcommand{\refname}{Список использованной литературы}
|
||||
|
||||
\begin{document}
|
||||
|
||||
% ============================================================================
|
||||
% ТИТУЛЬНЫЙ ЛИСТ
|
||||
% ============================================================================
|
||||
|
||||
\begin{titlepage}
|
||||
\begin{center}
|
||||
\vspace*{0.5cm}
|
||||
|
||||
{\Large \textbf{ФГБУ <<НМИЦ онкологии им. Н.Н. Блохина>> Минздрава России}}
|
||||
|
||||
\vspace{0.3cm}
|
||||
{\large Кафедра медицинской информатики и искусственного интеллекта}
|
||||
|
||||
\vspace{2.5cm}
|
||||
|
||||
{\Huge \textbf{ЛАБОРАТОРНАЯ РАБОТА №1}}
|
||||
|
||||
\vspace{0.5cm}
|
||||
{\huge \textbf{Аудит и подготовка медицинских данных}}
|
||||
|
||||
\vspace{0.5cm}
|
||||
{\Large для задач искусственного интеллекта в онкологии}
|
||||
|
||||
\vspace{2.5cm}
|
||||
|
||||
\begin{tabular}{p{0.4\textwidth}p{0.4\textwidth}}
|
||||
\textbf{Выполнил:} & \textbf{Руководитель:} \\
|
||||
\underline{\hspace{4cm}} & \underline{\hspace{4cm}} \\
|
||||
\textit{ФИО студента} & \textit{ФИО преподавателя} \\
|
||||
Группа: \underline{\hspace{2cm}} & Учёная степень: \underline{\hspace{2cm}} \\
|
||||
Вариант: \underline{\hspace{2cm}} & \\
|
||||
\end{tabular}
|
||||
|
||||
\vspace{2.5cm}
|
||||
|
||||
{\large Москва, 2026}
|
||||
|
||||
\end{center}
|
||||
\end{titlepage}
|
||||
|
||||
% ============================================================================
|
||||
% СОДЕРЖАНИЕ
|
||||
% ============================================================================
|
||||
|
||||
\tableofcontents
|
||||
\newpage
|
||||
|
||||
% ============================================================================
|
||||
% 1. ВВЕДЕНИЕ
|
||||
% ============================================================================
|
||||
|
||||
\section{Введение}
|
||||
|
||||
\subsection{Цель работы}
|
||||
|
||||
Сформировать у слушателей профессиональные компетенции в области аудита, предобработки и структурирования медицинских изображений для последующего обучения моделей искусственного интеллекта в задачах диагностики и лечения онкологических заболеваний.
|
||||
|
||||
\textbf{Задачи работы:}
|
||||
\begin{enumerate}
|
||||
\item Провести аудит структуры медицинского датасета в формате NRRD.
|
||||
\item Реализовать конвертацию полигональной разметки в бинарные маски.
|
||||
\item Выполнить распаковку 3D-данных в 2D-срезы формата YOLO.
|
||||
\item Создать конфигурационные файлы \texttt{predefined\_classes.txt} и \texttt{data.yaml}.
|
||||
\item Проанализировать роль клинического эксперта в подготовке данных.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Клинический контекст}
|
||||
|
||||
В рамках лабораторной работы используется датасет \texttt{1\_2236040\_zno\_cyst\_AF}, представляющий собой мультимодальные медицинские данные пациентов с новообразованиями почек. Исследование направлено на автоматическую детекцию и сегментацию анатомических структур почек и патологических образований.
|
||||
|
||||
\textbf{Объекты исследования:}
|
||||
\begin{itemize}
|
||||
\item Почки (правая и левая)
|
||||
\item Сегменты почек (верхний, средний, нижний)
|
||||
\item Патологические образования: злокачественные опухоли, доброкачественные опухоли, кисты, абсцессы
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Клиническая значимость:} Ранняя диагностика и точная дифференцировка патологических образований почек критически важны для выбора оптимальной тактики лечения и прогнозирования исходов. Внедрение методов искусственного интеллекта позволяет автоматизировать анализ медицинских изображений, снизить нагрузку на врачей и повысить точность диагностики.
|
||||
|
||||
\subsection{Обзор форматов данных}
|
||||
|
||||
\subsubsection{DICOM (Digital Imaging and Communications in Medicine)}
|
||||
|
||||
DICOM -- международный стандарт создания, хранения и передачи медицинской визуальной информации.
|
||||
|
||||
\textbf{Ключевые особенности:}
|
||||
\begin{itemize}
|
||||
\item Каждый файл содержит не только матрицу пикселей, но и богатый набор метаданных.
|
||||
\item Метаданные включают информацию о пациенте, модальности, параметрах сканирования, оборудовании.
|
||||
\item Аннотации областей интереса (ROI) хранятся в отдельных файлах DICOM-RT Structure Set.
|
||||
\item Формат поддерживает различные модальности: КТ, МРТ, ПЭТ, маммография и др.
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Структура DICOM-файла:}
|
||||
\begin{itemize}
|
||||
\item \textbf{Заголовок (метаданные)}: информация о пациенте, исследовании, серии, параметрах сканирования.
|
||||
\item \textbf{Тело (пиксельные данные)}: матрица интенсивностей.
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{NRRD (Nearly Raw Raster Data)}
|
||||
|
||||
NRRD -- формат, широко используемый в научных исследованиях для хранения многомерных растровых данных.
|
||||
|
||||
\textbf{Ключевые особенности:}
|
||||
\begin{itemize}
|
||||
\item Простая структура: текстовый заголовок + бинарные данные.
|
||||
\item Поддержка 3D и 4D массивов.
|
||||
\item Минимальные метаданные, но критически важные.
|
||||
\item Параметры \texttt{space directions} определяют направление осей.
|
||||
\item Параметр \texttt{space origin} задаёт начало координат.
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Пример структуры NRRD-файла:}
|
||||
\begin{verbatim}
|
||||
NRRD0004
|
||||
type: short
|
||||
dimension: 3
|
||||
sizes: 512 512 100
|
||||
spacings: 0.5 0.5 1.0
|
||||
space: left-posterior-superior
|
||||
space directions: (1,0,0) (0,1,0) (0,0,1)
|
||||
space origin: (0,0,0)
|
||||
... binary data ...
|
||||
\end{verbatim}
|
||||
|
||||
\subsubsection{Сравнение форматов}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Сравнение форматов DICOM и NRRD}
|
||||
\begin{tabular}{p{3.5cm}|p{4.5cm}|p{4.5cm}}
|
||||
\toprule
|
||||
\textbf{Характеристика} & \textbf{DICOM} & \textbf{NRRD} \\
|
||||
\midrule
|
||||
Структура & Файл + метаданные & Заголовок + бинарные данные \\
|
||||
Размер метаданных & Большой (медицинский контекст) & Минимальный (геометрия) \\
|
||||
Поддержка 3D & Да (через серии) & Да (родная) \\
|
||||
Читаемость & Требуется специализированное ПО & Поддерживается многими библиотеками \\
|
||||
Разметка & Отдельные файлы (RT Structure) & В том же файле или отдельном .seg \\
|
||||
Применение & Клиническая практика & Научные исследования \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
% ============================================================================
|
||||
% 2. ТЕОРЕТИЧЕСКАЯ ЧАСТЬ
|
||||
% ============================================================================
|
||||
|
||||
\section{Теоретическая часть}
|
||||
|
||||
\subsection{Формат DICOM и DICOM-RT Structure Set}
|
||||
|
||||
DICOM-RT Structure Set (DICOM-RTSS) -- это специальный объект DICOM, предназначенный для хранения структурных наборов, включая контуры областей интереса (ROI).
|
||||
|
||||
\textbf{Структура DICOM-RTSS:}
|
||||
\begin{itemize}
|
||||
\item \textbf{ROI Contour Sequence}: последовательность контуров для каждой ROI.
|
||||
\item \textbf{Contour Sequence}: точки контура в координатах DICOM.
|
||||
\item \textbf{ROI Observations}: информация о каждой ROI (тип, название).
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Формат хранения контуров:}
|
||||
\begin{verbatim}
|
||||
(3006, 0039) Contour Image Sequence
|
||||
(3006, 0040) Contour Geometric Type: CLOSED_PLANAR
|
||||
(3006, 0042) Contour Number: 1
|
||||
(3006, 0050) Contour Data: [x1, y1, z1, x2, y2, z2, ...]
|
||||
\end{verbatim}
|
||||
|
||||
Координаты контуров хранятся в физических координатах DICOM (мм) и могут быть преобразованы в пиксельные координаты с использованием аффинных преобразований.
|
||||
|
||||
\subsection{Формат NRRD: пространственная ориентация}
|
||||
|
||||
Для работы с 3D-данными критически важно сохранение пространственной ориентации. Параметры \texttt{space directions} и \texttt{space origin} определяют геометрию объёма.
|
||||
|
||||
\textbf{Параметры ориентации:}
|
||||
\begin{itemize}
|
||||
\item \texttt{space directions}: матрица направления осей.
|
||||
\item \texttt{space origin}: координаты начала координат.
|
||||
\item \texttt{spacings}: расстояния между пикселями по каждой оси.
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Математическое представление:}
|
||||
\begin{equation}
|
||||
\mathbf{p}_{world} = \mathbf{D} \cdot \mathbf{p}_{voxel} + \mathbf{o}
|
||||
\label{eq:orientation}
|
||||
\end{equation}
|
||||
где:
|
||||
\begin{itemize}
|
||||
\item $\mathbf{p}_{world}$ -- координаты в физическом пространстве.
|
||||
\item $\mathbf{D}$ -- матрица направления ($3 \times 3$).
|
||||
\item $\mathbf{p}_{voxel}$ -- координаты вокселя.
|
||||
\item $\mathbf{o}$ -- смещение (space origin).
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Пример матрицы направления:}
|
||||
\begin{equation}
|
||||
\mathbf{D} = \begin{pmatrix}
|
||||
-1 & 0 & 0 \\
|
||||
0 & 1 & 0 \\
|
||||
0 & 0 & 1
|
||||
\end{pmatrix}
|
||||
\end{equation}
|
||||
|
||||
Потеря этих параметров при конвертации делает невозможным использование данных для обучения 3D-нейронных сетей.
|
||||
|
||||
\subsection{Пайплайн подготовки данных для YOLO}
|
||||
|
||||
Стандартный пайплайн подготовки данных включает следующие этапы:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Аудит данных}: проверка структуры, целостности, соответствия форматам.
|
||||
\item \textbf{Извлечение срезов}: конвертация 3D-данных в 2D-срезы.
|
||||
\item \textbf{Синхронизация изображений и разметки}: соответствие срезов и масок.
|
||||
\item \textbf{Нормализация изображений}: приведение интенсивностей к единому диапазону.
|
||||
\item \textbf{Создание разметки в формате YOLO}: конвертация полигонов в bbox и полигоны.
|
||||
\item \textbf{Структурирование данных}: организация файлов по стандартной структуре.
|
||||
\item \textbf{Создание конфигурационных файлов}: \texttt{predefined\_classes.txt} и \texttt{data.yaml}.
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Стандартная структура директорий:}
|
||||
\begin{verbatim}
|
||||
experiment/
|
||||
- images/ # 2D-срезы для обучения
|
||||
- images_labels/ # Bbox-разметка (YOLO формат)
|
||||
- polygons/ # Полигоны для сегментации
|
||||
- images_result/ # Визуализация результатов
|
||||
- masks_sam/ # Бинарные маски
|
||||
- predefined_classes.txt # Схема классов
|
||||
- data.yaml # Конфиг YOLO
|
||||
\end{verbatim}
|
||||
|
||||
\subsection{Роль врача-эксперта и понятие клинической <<легенды>>}
|
||||
|
||||
Автоматизированная обработка не может заменить клиническую экспертизу. Под клинической <<легендой>> датасета понимается полное и точное описание данных.
|
||||
|
||||
\textbf{Компоненты клинической <<легенды>>:}
|
||||
\begin{itemize}
|
||||
\item Модальность исследования (КТ, МРТ, ПЭТ и др.)
|
||||
\item Протокол сканирования
|
||||
\item Подтверждённый диагноз
|
||||
\item Критерии включения и исключения
|
||||
\item Правила разметки областей интереса
|
||||
\item Источник данных
|
||||
\item Версия программного обеспечения сканера
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Риски отсутствия экспертизы:}
|
||||
\begin{enumerate}
|
||||
\item \textbf{Формирование ложных паттернов}: нейросеть может научиться распознавать не патологию, а артефакты сканирования или особенности оборудования (<<shortcut learning>>).
|
||||
\item \textbf{Ошибки в неструктурированных данных}: файлы без расширений или с некорректными именами могут быть неверно интерпретированы.
|
||||
\item \textbf{Потеря клинического контекста}: без верификации <<легенды>> датасета обучение модели становится бессмысленным.
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Обязательные меры:}
|
||||
\begin{itemize}
|
||||
\item Верификация выборки квалифицированным врачом-радиологом или онкологом.
|
||||
\item Документирование всех этапов подготовки данных.
|
||||
\item Фиксация модальности, версии ПО и источника данных в метаданных проекта.
|
||||
\end{itemize}
|
||||
|
||||
% ============================================================================
|
||||
% 3. ПРАКТИЧЕСКАЯ ЧАСТЬ
|
||||
% ============================================================================
|
||||
|
||||
\section{Практическая часть}
|
||||
|
||||
\subsection{Аудит структуры датасета}
|
||||
|
||||
\subsubsection{Анализ директории \texttt{1\_2236040\_zno\_cyst\_AF}}
|
||||
|
||||
Первым шагом является анализ структуры полученной директории с данными.
|
||||
|
||||
\textbf{Исходная структура:}
|
||||
\begin{verbatim}
|
||||
1_2236040_zno_cyst_AF/
|
||||
- 501 arterial ax 1mm iDose (5).nrrd # Исходные 3D данные
|
||||
- Segmentation.seg.nrrd # Сегментационная маска
|
||||
- dcm/ # DICOM-срезы (1042 файла)
|
||||
- images/ # PNG-срезы (300 файлов)
|
||||
- images_labels/ # Bbox-разметка
|
||||
- polygons/ # Полигоны для сегментации
|
||||
- images_result/ # Визуализация результатов
|
||||
- masks_sam/ # Маски SAM
|
||||
\end{verbatim}
|
||||
|
||||
\textbf{Статистика данных:}
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Статистика датасета}
|
||||
\begin{tabular}{l|r}
|
||||
\toprule
|
||||
\textbf{Тип данных} & \textbf{Количество} \\
|
||||
\midrule
|
||||
DICOM-файлы & 1042 \\
|
||||
PNG-изображения & 300 \\
|
||||
Файлы разметки (bbox) & 300 \\
|
||||
Файлы разметки (polygons) & 300 \\
|
||||
Классы & 12 \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\textbf{Выявленные особенности:}
|
||||
\begin{enumerate}
|
||||
\item Исходные данные представлены в формате NRRD (изображение и сегментационная маска).
|
||||
\item DICOM-файлы сгенерированы из NRRD.
|
||||
\item PNG-изображения извлечены из определённого диапазона срезов (573--872).
|
||||
\item Разметка представлена в формате YOLO как для детекции (bbox), так и для сегментации (полигоны).
|
||||
\item Присутствуют \texttt{.gitkeep} файлы для сохранения пустых директорий.
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Проверка целостности данных}
|
||||
|
||||
Для проверки целостности необходимо:
|
||||
\begin{enumerate}
|
||||
\item Сопоставить количество изображений и файлов разметки.
|
||||
\item Проверить соответствие идентификаторов срезов.
|
||||
\item Валидировать форматы координат в файлах разметки.
|
||||
\item Проверить отсутствие повреждённых файлов.
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Пример проверки соответствия:}
|
||||
\begin{lstlisting}
|
||||
from pathlib import Path
|
||||
|
||||
images_dir = Path("data/1_2236040_zno_cyst_AF/images")
|
||||
labels_dir = Path("data/1_2236040_zno_cyst_AF/images_labels")
|
||||
|
||||
images = set(f.stem for f in images_dir.glob("*.png"))
|
||||
labels = set(f.stem for f in labels_dir.glob("*.txt"))
|
||||
|
||||
missing_labels = images - labels
|
||||
missing_images = labels - images
|
||||
|
||||
print(len(images), len(labels))
|
||||
print(len(missing_labels), len(missing_images))
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Конвертация полигонов в бинарные маски}
|
||||
|
||||
\subsubsection{Извлечение координат из DICOM-RT}
|
||||
|
||||
Для конвертации полигонов из DICOM-RT Structure Set в бинарные маски используется библиотека \texttt{pydicom}.
|
||||
|
||||
\textbf{Алгоритм конвертации:}
|
||||
\begin{enumerate}
|
||||
\item Чтение DICOM-RT Structure Set.
|
||||
\item Извлечение контуров областей интереса (ROI).
|
||||
\item Преобразование физических координат в пиксельные.
|
||||
\item Растеризация полигонов в бинарные маски.
|
||||
\item Визуальный контроль качества.
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Реализация:}
|
||||
\begin{lstlisting}
|
||||
import numpy as np
|
||||
from skimage.draw import polygon
|
||||
|
||||
def rasterize_contour(coords, shape):
|
||||
mask = np.zeros(shape, dtype=np.uint8)
|
||||
rr, cc = polygon(coords[:, 1], coords[:, 0], shape)
|
||||
mask[rr, cc] = 1
|
||||
return mask
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Визуальный контроль качества}
|
||||
|
||||
После конвертации необходимо визуально проверить качество полученных масок.
|
||||
|
||||
\textbf{Скрипт для визуализации:}
|
||||
\begin{lstlisting}
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def show_mask(image, mask):
|
||||
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
|
||||
axes[0].imshow(image, cmap='gray')
|
||||
axes[0].set_title('Original')
|
||||
axes[0].axis('off')
|
||||
axes[1].imshow(image, cmap='gray')
|
||||
axes[1].imshow(mask, cmap='jet', alpha=0.5)
|
||||
axes[1].set_title('Mask')
|
||||
axes[1].axis('off')
|
||||
plt.show()
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Типичные проблемы:}
|
||||
\begin{itemize}
|
||||
\item <<Разрывы>> контуров из-за повреждённых тегов.
|
||||
\item Смещение контуров из-за ошибок в аффинных преобразованиях.
|
||||
\item Пропущенные срезы в многослойных структурах.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Распаковка NRRD в 2D-срезы}
|
||||
|
||||
\subsubsection{Загрузка NRRD-файлов}
|
||||
|
||||
Для работы с NRRD-файлами используется библиотека \texttt{nrrd}.
|
||||
|
||||
\textbf{Загрузка изображения и маски:}
|
||||
\begin{lstlisting}
|
||||
import nrrd
|
||||
|
||||
def load_nrrd(path):
|
||||
data, header = nrrd.read(path)
|
||||
return data, header
|
||||
|
||||
img_data, img_header = load_nrrd("image.nrrd")
|
||||
seg_data, seg_header = load_nrrd("seg.seg.nrrd")
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Синхронизация срезов}
|
||||
|
||||
Критически важно сохранить соответствие между срезами изображения и маски.
|
||||
|
||||
\textbf{Синхронизация:}
|
||||
\begin{lstlisting}
|
||||
def extract_slice(data, z):
|
||||
return data[:, :, z].T
|
||||
|
||||
img_slice = extract_slice(img_data, 600)
|
||||
seg_slice = extract_slice(seg_data, 600)
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Сохранение пространственной ориентации}
|
||||
|
||||
При конвертации необходимо сохранить параметры ориентации.
|
||||
|
||||
\textbf{Сохранение параметров:}
|
||||
\begin{lstlisting}
|
||||
def save_orientation(header, path):
|
||||
params = {
|
||||
'space': header.get('space', ''),
|
||||
'space_directions': header.get('space directions', ''),
|
||||
'space_origin': header.get('space origin', ''),
|
||||
'spacings': header.get('spacings', ''),
|
||||
}
|
||||
with open(path, 'w') as f:
|
||||
for k, v in params.items():
|
||||
f.write(k + ': ' + str(v) + '\n')
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Создание конфигурационных файлов}
|
||||
|
||||
\subsubsection{\texttt{predefined\_classes.txt}}
|
||||
|
||||
Файл \texttt{predefined\_classes.txt} содержит полную схему классов для эксперимента.
|
||||
|
||||
\textbf{Содержимое файла:}
|
||||
\begin{lstlisting}
|
||||
right_kidney_ID1
|
||||
right_kidney_upper_segment_ID2
|
||||
right_kidney_middle_segment_ID3
|
||||
right_kidney_lower_segment_ID4
|
||||
left_kidney_ID5
|
||||
left_kidney_upper_segment_ID6
|
||||
left_kidney_middle_segment_ID7
|
||||
left_kidney_lower_segment_ID8
|
||||
malignant_tumor_ID9
|
||||
benign_tumor_ID10
|
||||
cyst_ID11
|
||||
abscess_ID12
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Формат:} один класс на строку, позиция в файле = YOLO index (0-based).
|
||||
|
||||
\textbf{Особенности:}
|
||||
\begin{enumerate}
|
||||
\item Каждый эксперимент имеет свой собственный файл классов.
|
||||
\item Позволяет использовать разные наборы классов для разных препаратов.
|
||||
\item Скрипт \texttt{ttv\_freq2.py} автоматически загружает этот файл.
|
||||
\item Обеспечивает согласованность классов между различными задачами (детекция, сегментация).
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{\texttt{data.yaml}}
|
||||
|
||||
Файл \texttt{data.yaml} является основным конфигурационным файлом для YOLO.
|
||||
|
||||
\textbf{Содержимое файла:}
|
||||
\begin{lstlisting}
|
||||
path: D:/ai-med-edu/data/1_2236040_zno_cyst_AF
|
||||
train: images
|
||||
val: images
|
||||
test: images
|
||||
nc: 12
|
||||
names: ['right_kidney_ID1', 'right_kidney_upper_segment_ID2']
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Параметры:}
|
||||
\begin{itemize}
|
||||
\item \texttt{path}: абсолютный путь к папке эксперимента.
|
||||
\item \texttt{train}/\texttt{val}/\texttt{test}: пути к файлам со списками изображений.
|
||||
\item \texttt{nc}: количество классов (должно совпадать с количеством строк в \texttt{predefined\_classes.txt}).
|
||||
\item \texttt{names}: список названий классов в порядке их индексов (0-based).
|
||||
\end{itemize}
|
||||
|
||||
% ============================================================================
|
||||
% 4. РЕЗУЛЬТАТЫ
|
||||
% ============================================================================
|
||||
|
||||
\section{Результаты}
|
||||
|
||||
\subsection{Структура директорий после обработки}
|
||||
|
||||
После выполнения всех шагов обработки структура директорий имеет следующий вид:
|
||||
|
||||
\begin{verbatim}
|
||||
1_2236040_zno_cyst_AF/
|
||||
- images/ # PNG-срезы (300 файлов)
|
||||
- slice_0573.png
|
||||
- slice_0574.png
|
||||
- ...
|
||||
- images_labels/ # Bbox-разметка
|
||||
- slice_0573.txt
|
||||
- slice_0574.txt
|
||||
- ...
|
||||
- polygons/ # Полигоны
|
||||
- slice_0573.txt
|
||||
- slice_0574.txt
|
||||
- ...
|
||||
- images_result/ # Визуализация
|
||||
- slice_0573_preview.png
|
||||
- slice_0574_preview.png
|
||||
- ...
|
||||
- masks_sam/ # Бинарные маски
|
||||
- slice_0573_class_8_obj_0000.png
|
||||
- ...
|
||||
- dcm/ # DICOM-срезы (1042 файла)
|
||||
- slice_0000.dcm
|
||||
- slice_0001.dcm
|
||||
- ...
|
||||
- predefined_classes.txt # Схема классов (12 классов)
|
||||
- data.yaml # Конфиг YOLO
|
||||
\end{verbatim}
|
||||
|
||||
\subsection{Примеры разметки}
|
||||
|
||||
\subsubsection{Формат BBOX (детекция)}
|
||||
|
||||
Файл: \texttt{images\_labels/slice\_0573.txt}
|
||||
\begin{verbatim}
|
||||
8 0.354492 0.541992 0.017578 0.021484
|
||||
\end{verbatim}
|
||||
|
||||
\textbf{Формат:} \texttt{<class\_id> <x\_center> <y\_center> <width> <height>}
|
||||
|
||||
\textbf{Где:}
|
||||
\begin{itemize}
|
||||
\item \texttt{class\_id}: индекс класса (0-based).
|
||||
\item \texttt{x\_center}, \texttt{y\_center}: координаты центра объекта (нормализованные от 0 до 1).
|
||||
\item \texttt{width}, \texttt{height}: размеры объекта (нормализованные от 0 до 1).
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Формат POLYGON (сегментация)}
|
||||
|
||||
Файл: \texttt{images\_labels/polygons/slice\_0573.txt}
|
||||
\begin{verbatim}
|
||||
8 0.349609 0.531250 0.345703 0.535156 0.345703 0.542969 ...
|
||||
\end{verbatim}
|
||||
|
||||
\textbf{Формат:} \texttt{<class\_id> <x1> <y1> <x2> <y2> ... <xn> <yn>}
|
||||
|
||||
\textbf{Где:}
|
||||
\begin{itemize}
|
||||
\item \texttt{class\_id}: индекс класса (0-based).
|
||||
\item \texttt{x1}, \texttt{y1}, \texttt{x2}, \texttt{y2}, ...: координаты точек полигона (нормализованные от 0 до 1).
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Статистика по классам}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Распределение классов в датасете}
|
||||
\begin{tabular}{l|r|r|r|r}
|
||||
\toprule
|
||||
\textbf{Класс} & \textbf{ID (1-based)} & \textbf{YOLO idx} & \textbf{Количество} & \textbf{Процент} \\
|
||||
\midrule
|
||||
right\_kidney & 1 & 0 & 300 & 100.0\% \\
|
||||
right\_kidney\_upper\_segment & 2 & 1 & 35 & 11.7\% \\
|
||||
right\_kidney\_middle\_segment & 3 & 2 & 55 & 18.3\% \\
|
||||
right\_kidney\_lower\_segment & 4 & 3 & 47 & 15.7\% \\
|
||||
left\_kidney & 5 & 4 & 26 & 8.7\% \\
|
||||
left\_kidney\_upper\_segment & 6 & 5 & 28 & 9.3\% \\
|
||||
left\_kidney\_middle\_segment & 7 & 6 & 36 & 12.0\% \\
|
||||
left\_kidney\_lower\_segment & 8 & 7 & 44 & 14.7\% \\
|
||||
malignant\_tumor & 9 & 8 & 52 & 17.3\% \\
|
||||
benign\_tumor & 10 & 9 & 38 & 12.7\% \\
|
||||
cyst & 11 & 10 & 41 & 13.7\% \\
|
||||
abscess & 12 & 11 & 12 & 4.0\% \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\textbf{Примечание:} Проценты указаны относительно общего количества изображений (300).
|
||||
|
||||
% ============================================================================
|
||||
% 5. ВЫВОДЫ
|
||||
% ============================================================================
|
||||
|
||||
\section{Выводы}
|
||||
|
||||
В ходе выполнения лабораторной работы были получены следующие результаты:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Проведён аудит структуры датасета}: выявлены форматы данных (NRRD, DICOM, PNG), количество файлов и их соответствие.
|
||||
|
||||
\item \textbf{Реализована конвертация полигонов в бинарные маски}: разработан пайплайн для преобразования полигональной разметки в растровые маски, пригодные для расчёта радиометрических характеристик и обучения сегментационных моделей.
|
||||
|
||||
\item \textbf{Выполнена распаковка NRRD в 2D-срезы}: разработан автоматизированный скрипт, который извлекает 2D-срезы из 3D-массива, синхронизирует их с соответствующими масками и организует файловую систему по единому шаблону.
|
||||
|
||||
\item \textbf{Созданы конфигурационные файлы}: \texttt{predefined\_classes.txt} (12 классов) и \texttt{data.yaml} -- единая точка управления классами и путями к данным.
|
||||
|
||||
\item \textbf{Подтверждена роль врача-эксперта}: верификация клинической <<легенды>> датасета является обязательным условием для запуска обучения модели, предотвращая формирование ложных паттернов.
|
||||
|
||||
\item \textbf{Выявлены системные риски}: потеря пространственной ориентации при распаковке NRRD, повреждённые теги в DICOM-RT, отсутствие клинической экспертизы.
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Рекомендации по масштабированию:}
|
||||
\begin{enumerate}
|
||||
\item Использовать \texttt{predefined\_classes.txt} как единый источник истины для всех экспериментов.
|
||||
\item Автоматизировать проверку целостности данных перед обработкой.
|
||||
\item Внедрить обязательную визуальную верификацию масок врачом-экспертом.
|
||||
\item Сохранять параметры пространственной ориентации при любой конвертации.
|
||||
\end{enumerate}
|
||||
|
||||
% ============================================================================
|
||||
% 6. КОНТРОЛЬНЫЕ ВОПРОСЫ
|
||||
% ============================================================================
|
||||
|
||||
\section{Контрольные вопросы}
|
||||
|
||||
\begin{enumerate}
|
||||
\item В чём заключаются принципиальные различия между форматами DICOM и NRRD? В каких случаях предпочтительнее использовать каждый из них при организации радиомических исследований?
|
||||
|
||||
\item Почему файлы DICOM-RT Structure Set требуют особой проверки целостности перед конвертацией в бинарные маски? Какие последствия могут возникнуть при наличии повреждённых тегов?
|
||||
|
||||
\item Какую роль играют метаданные \texttt{space directions} и \texttt{space origin} в формате NRRD? Почему их потеря критична при работе с 3D-моделями и обучении нейронных сетей?
|
||||
|
||||
\item Что такое <<клиническая легенда>> датасета и почему её верификация врачом-экспертом является обязательным этапом перед обучением модели ИИ?
|
||||
|
||||
\item Какие преимущества даёт использование конфигурационных файлов \texttt{data.yaml} и \texttt{predefined\_classes.txt} при масштабировании проекта и подключении новых когорт пациентов?
|
||||
|
||||
\item Проанализируйте структуру закреплённого за вами датасета. К какой группе (DICOM или NRRD) он относится? Какие особенности хранения данных и разметки вы выявили?
|
||||
|
||||
\item Опишите пошагово процесс конвертации полигональной разметки в бинарную маску для вашего формата данных. Какие библиотеки Python вы использовали и почему?
|
||||
|
||||
\item Какие радиометрические характеристики были рассчитаны клиент-серверным приложением для областей интереса вашего датасета? Какие из этих признаков, на ваш взгляд, наиболее информативны для решения клинической задачи?
|
||||
|
||||
\item Если бы вам потребовалось подключить к проекту новый датасет в неизвестном формате, какую последовательность действий вы бы предприняли? На каком этапе потребовалось бы привлечение врача-эксперта?
|
||||
|
||||
\item Предложите стратегию масштабирования текущего датасета для его последующего использования в реальном клиническом внедрении. Какие дополнительные данные и в каком объёме необходимо привлечь?
|
||||
\end{enumerate}
|
||||
|
||||
% ============================================================================
|
||||
% 7. СПИСОК ЛИТЕРАТУРЫ
|
||||
% ============================================================================
|
||||
|
||||
\section{Список литературы}
|
||||
|
||||
\begin{enumerate}
|
||||
\item Владзимирский, А. В. Компьютерное зрение в лучевой диагностике: первый этап Московского эксперимента / А. В. Владзимирский, Ю. А. Васильев, К. М. Арзамасов [и др.]. -- 2-е изд. -- Москва : ООО <<Издательские решения>>, 2023. -- 388 с. -- ISBN 978-5-0059-3043-9.
|
||||
|
||||
\item Гавриченков, Ю. Д. Системы искусственного интеллекта : учебно-методическое пособие / Ю. Д. Гавриченков, В. Ю. Переверзев. -- Самара : Медицинский университет <<Реавиз>>, 2024. -- 55 с.
|
||||
|
||||
\item Поляков, Е. В. Цифровая обработка медицинских изображений : учебное пособие / Е. В. Поляков, В. В. Дмитриева, А. А. Фроня. -- Москва : НИЯУ МИФИ, 2024. -- 100 с.
|
||||
|
||||
\item Савченко, Е. Ю. Основы и применение нейронных сетей: теория, практика, инновации : учебное пособие / Е. Ю. Савченко. -- Бишкек : Нео Принт, 2024. -- 116 с.
|
||||
|
||||
\item Молодяков, С. А. Применение функций OpenCV в компьютерном зрении (60 примеров на Python) / С. А. Молодяков. -- Санкт-Петербург : Изд-во Политехн. ун-та, 2022. -- 296 с.
|
||||
|
||||
\item Jocher, G. Ultralytics YOLOv8 Documentation. -- URL: https://docs.ultralytics.com/ (дата обращения: 21.08.2026).
|
||||
|
||||
\item van Griethuysen, J. J. M. Computational Radiomics System to Decode the Radiographic Phenotype / J. J. M. van Griethuysen, A. Fedorov, C. Parmar [et al.] // Cancer Research. -- 2017. -- Vol. 77, No. 21. -- P. e104--e107.
|
||||
\end{enumerate}
|
||||
|
||||
% ============================================================================
|
||||
% ПРИЛОЖЕНИЕ
|
||||
% ============================================================================
|
||||
|
||||
\appendix
|
||||
\section{Приложение: Код скрипта \texttt{nrrd\_to\_yolo.py}}
|
||||
|
||||
\begin{lstlisting}[basicstyle=\ttfamily\footnotesize]
|
||||
import os
|
||||
import re
|
||||
import numpy as np
|
||||
import nrrd
|
||||
import pydicom
|
||||
from pydicom.uid import ExplicitVRLittleEndian
|
||||
from pydicom.uid import generate_uid
|
||||
from pathlib import Path
|
||||
import matplotlib
|
||||
matplotlib.use('Agg')
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.patches import Rectangle
|
||||
from matplotlib.colors import ListedColormap
|
||||
from scipy import ndimage
|
||||
import cv2
|
||||
|
||||
BASE_DIR = "data/1_2236040_zno_cyst_AF"
|
||||
IMG_NRRD = "501 arterial ax 1mm iDose (5).nrrd"
|
||||
SEG_NRRD = "Segmentation.seg.nrrd"
|
||||
CT_CMAP = 'gray'
|
||||
POLY_EPSILON = 0.01
|
||||
|
||||
def extract_segment_metadata(header):
|
||||
names = {}
|
||||
colors = {}
|
||||
for key, value in header.items():
|
||||
if key.startswith('Segment') and key.endswith('_LabelValue'):
|
||||
match = re.search(r'Segment(\d+)_LabelValue', key)
|
||||
if match:
|
||||
seg_idx = int(match.group(1))
|
||||
label_val = int(float(value))
|
||||
name_key = f'Segment{seg_idx}_Name'
|
||||
names[label_val] = header.get(name_key, '')
|
||||
color_key = f'Segment{seg_idx}_Color'
|
||||
color_str = header.get(color_key, '')
|
||||
if color_str:
|
||||
parts = color_str.strip().split()
|
||||
if len(parts) >= 3:
|
||||
r, g, b = [int(float(c) * 255) for c in parts[:3]]
|
||||
colors[label_val] = f"#{r:02x}{g:02x}{b:02x}"
|
||||
return names, colors
|
||||
|
||||
def create_dicom_from_slice(slice_data, z_index):
|
||||
ds = pydicom.Dataset()
|
||||
ds.file_meta = pydicom.Dataset()
|
||||
ds.file_meta.TransferSyntaxUID = ExplicitVRLittleEndian
|
||||
ds.file_meta.MediaStorageSOPClassUID = '1.2.840.10008.5.1.4.1.1.2'
|
||||
ds.file_meta.MediaStorageSOPInstanceUID = generate_uid()
|
||||
ds.file_meta.ImplementationClassUID = generate_uid()
|
||||
ds.SOPClassUID = ds.file_meta.MediaStorageSOPClassUID
|
||||
ds.SOPInstanceUID = ds.file_meta.MediaStorageSOPInstanceUID
|
||||
ds.PatientName = "ANON^PATIENT"
|
||||
ds.PatientID = "000000"
|
||||
ds.StudyDate = "20260602"
|
||||
ds.Modality = "CT"
|
||||
ds.InstanceNumber = str(z_index)
|
||||
ds.Rows, ds.Columns = slice_data.shape
|
||||
ds.PixelSpacing = [1.0, 1.0]
|
||||
ds.SliceThickness = 1.0
|
||||
ds.BitsAllocated = 16
|
||||
ds.BitsStored = 16
|
||||
ds.HighBit = 15
|
||||
ds.PixelRepresentation = 1
|
||||
ds.ImagePositionPatient = [0.0, 0.0, float(z_index)]
|
||||
ds.ImageOrientationPatient = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0]
|
||||
ds.SamplesPerPixel = 1
|
||||
ds.PhotometricInterpretation = "MONOCHROME2"
|
||||
ds.PixelData = slice_data.tobytes()
|
||||
return ds
|
||||
|
||||
def extract_polygon(mask_uint8):
|
||||
contours, _ = cv2.findContours(mask_uint8, cv2.RETR_EXTERNAL,
|
||||
cv2.CHAIN_APPROX_SIMPLE)
|
||||
if not contours:
|
||||
return None
|
||||
largest_contour = max(contours, key=cv2.contourArea)
|
||||
epsilon = POLY_EPSILON * cv2.arcLength(largest_contour, True)
|
||||
approx = cv2.approxPolyDP(largest_contour, epsilon, True)
|
||||
if len(approx) < 3:
|
||||
return None
|
||||
points = [(int(pt[0][0]), int(pt[0][1])) for pt in approx]
|
||||
return points
|
||||
|
||||
def save_png_safe(path, image):
|
||||
success, buffer = cv2.imencode('.png', image)
|
||||
if not success:
|
||||
raise RuntimeError("cv2.imencode failed")
|
||||
path.write_bytes(buffer.tobytes())
|
||||
|
||||
def main():
|
||||
base_path = Path(BASE_DIR)
|
||||
if not base_path.exists():
|
||||
print("Error: directory not found")
|
||||
return
|
||||
print("Working directory:", base_path.absolute())
|
||||
for d in ["images", "dcm", "images_labels", "images_labels/polygons",
|
||||
"images_result", "images_result/masks_sam"]:
|
||||
(base_path / d).mkdir(exist_ok=True)
|
||||
print("Loading NRRD...")
|
||||
img_data, _ = nrrd.read(base_path / IMG_NRRD)
|
||||
seg_data, seg_header = nrrd.read(base_path / SEG_NRRD)
|
||||
if img_data.shape != seg_data.shape:
|
||||
raise ValueError("Shape mismatch")
|
||||
SEGMENT_NAMES, SEGMENT_COLORS = extract_segment_metadata(seg_header)
|
||||
if not SEGMENT_NAMES:
|
||||
print("No metadata, using placeholders")
|
||||
unique = np.unique(seg_data[seg_data > 0])
|
||||
SEGMENT_NAMES = {int(l): f"Class_{int(l)}" for l in unique}
|
||||
SEGMENT_COLORS = {int(l): f"#{np.random.randint(0, 0xFFFFFF):06x}"
|
||||
for l in unique}
|
||||
sorted_labels = sorted(SEGMENT_NAMES.keys())
|
||||
class_names = [SEGMENT_NAMES[l] for l in sorted_labels]
|
||||
max_label = max(sorted_labels)
|
||||
color_map_list = ['#000000'] * (max_label + 1)
|
||||
for lbl, col in SEGMENT_COLORS.items():
|
||||
if lbl <= max_label:
|
||||
color_map_list[lbl] = col
|
||||
custom_cmap = ListedColormap(color_map_list)
|
||||
print("Found classes:", class_names)
|
||||
(base_path / "predefined_classes.txt").write_text("\n".join(class_names))
|
||||
W, H, D = img_data.shape
|
||||
count = 0
|
||||
mask_count = 0
|
||||
for z in range(D):
|
||||
img_slice = img_data[:, :, z].T
|
||||
seg_slice = seg_data[:, :, z].T
|
||||
create_dicom_from_slice(img_slice.astype(np.int16), z).save_as(
|
||||
base_path / "dcm" / f"slice_{z:04d}.dcm")
|
||||
p_min, p_max = np.percentile(img_slice, [0.5, 99.5])
|
||||
img_uint8 = (np.clip(img_slice, p_min, p_max) - p_min) / (p_max - p_min + 1e-8) * 255
|
||||
img_uint8 = img_uint8.astype(np.uint8)
|
||||
slice_labels = np.unique(seg_slice[seg_slice > 0])
|
||||
slice_labels = [int(l) for l in slice_labels]
|
||||
if len(slice_labels) > 0:
|
||||
bbox_lines = []
|
||||
polygon_lines = []
|
||||
fig, ax = plt.subplots(figsize=(img_slice.shape[1]/100,
|
||||
img_slice.shape[0]/100))
|
||||
ax.imshow(img_uint8, cmap=CT_CMAP)
|
||||
ax.imshow(seg_slice, cmap=custom_cmap, alpha=0.4)
|
||||
H_curr, W_curr = img_slice.shape
|
||||
for label in slice_labels:
|
||||
mask_class = (seg_slice == label)
|
||||
labeled_objs, num_objs = ndimage.label(mask_class,
|
||||
structure=np.ones((3,3)))
|
||||
for obj_idx in range(1, num_objs + 1):
|
||||
obj_mask = (labeled_objs == obj_idx)
|
||||
ys, xs = np.where(obj_mask)
|
||||
if len(ys) == 0:
|
||||
continue
|
||||
x_min, y_min, x_max, y_max = xs.min(), ys.min(), xs.max(), ys.max()
|
||||
xc = (x_min + x_max) / 2.0
|
||||
yc = (y_min + y_max) / 2.0
|
||||
bw = x_max - x_min
|
||||
bh = y_max - y_min
|
||||
yolo_class_id = sorted_labels.index(label)
|
||||
bbox_lines.append(
|
||||
f"{yolo_class_id} {xc/W_curr:.6f} {yc/H_curr:.6f} "
|
||||
f"{bw/W_curr:.6f} {bh/H_curr:.6f}")
|
||||
obj_mask_uint8 = (obj_mask * 255).astype(np.uint8)
|
||||
polygon = extract_polygon(obj_mask_uint8)
|
||||
if polygon:
|
||||
norm_points = []
|
||||
for (px, py) in polygon:
|
||||
norm_points.append(f"{px/W_curr:.6f}")
|
||||
norm_points.append(f"{py/H_curr:.6f}")
|
||||
polygon_lines.append(f"{yolo_class_id} " + " ".join(norm_points))
|
||||
single_mask = np.zeros((H_curr, W_curr), dtype=np.uint8)
|
||||
single_mask[obj_mask] = 255
|
||||
mask_filename = (f"slice_{z:04d}_class_{yolo_class_id}_"
|
||||
f"obj_{(obj_idx-1):04d}.png")
|
||||
mask_path = base_path / "images_result" / "masks_sam" / mask_filename
|
||||
try:
|
||||
save_png_safe(mask_path, single_mask)
|
||||
mask_count += 1
|
||||
except Exception as e:
|
||||
print("Error saving mask:", e)
|
||||
color_hex = color_map_list[label]
|
||||
rect = Rectangle((x_min, y_min), bw, bh, linewidth=2,
|
||||
edgecolor=color_hex, facecolor='none',
|
||||
linestyle='-', alpha=0.7)
|
||||
ax.add_patch(rect)
|
||||
if polygon:
|
||||
poly_pts = np.array(polygon)
|
||||
closed_pts = np.vstack([poly_pts, poly_pts[0:1]])
|
||||
ax.plot(closed_pts[:, 0], closed_pts[:, 1],
|
||||
color=color_hex, linewidth=2.5,
|
||||
linestyle='--', alpha=0.9)
|
||||
(base_path / "images_labels" / f"slice_{z:04d}.txt").write_text(
|
||||
"\n".join(bbox_lines) + "\n")
|
||||
if polygon_lines:
|
||||
(base_path / "images_labels" / "polygons" / f"slice_{z:04d}.txt").write_text(
|
||||
"\n".join(polygon_lines) + "\n")
|
||||
plt.imsave(base_path / "images" / f"slice_{z:04d}.png",
|
||||
img_uint8, cmap=CT_CMAP, format='png')
|
||||
ax.set_title(f"Slice {z}")
|
||||
ax.axis('off')
|
||||
plt.tight_layout(pad=0)
|
||||
plt.savefig(base_path / "images_result" / f"slice_{z:04d}_preview.png",
|
||||
dpi=150, bbox_inches='tight')
|
||||
plt.close(fig)
|
||||
count += 1
|
||||
(base_path / "data.yaml").write_text(
|
||||
f"path: {base_path.absolute()}\n"
|
||||
f"train: images\n"
|
||||
f"val: images\n"
|
||||
f"test: images\n"
|
||||
f"nc: {len(class_names)}\n"
|
||||
f"names: {class_names}\n")
|
||||
print("Done! Processed slices:", count)
|
||||
print("Created binary masks:", mask_count)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
print("Error:", e)
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
\end{lstlisting}
|
||||
|
||||
\end{document}
|
||||
LFS
BIN
Binary file not shown.
+660
@@ -0,0 +1,660 @@
|
||||
% ============================================================================
|
||||
% ЛАБОРАТОРНАЯ РАБОТА №2
|
||||
% АНАЛИЗ РАДИОМЕТРИЧЕСКИХ ПРИЗНАКОВ
|
||||
% ============================================================================
|
||||
% КОМПИЛЯЦИЯ: pdflatex (ДВА ПРОХОДА)
|
||||
% ============================================================================
|
||||
|
||||
\documentclass[12pt,a4paper]{article}
|
||||
|
||||
% ============================================================================
|
||||
% ПРЕАМБУЛА
|
||||
% ============================================================================
|
||||
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T2A]{fontenc}
|
||||
\usepackage[russian]{babel}
|
||||
|
||||
\usepackage{amsmath,amssymb,amsfonts}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{listings}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{geometry}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{longtable}
|
||||
\usepackage{caption}
|
||||
\usepackage{subcaption}
|
||||
\usepackage{titlesec}
|
||||
\usepackage{float}
|
||||
\usepackage{array}
|
||||
\usepackage{multirow}
|
||||
\usepackage{enumitem}
|
||||
|
||||
\geometry{left=2.5cm,right=2cm,top=2cm,bottom=2cm}
|
||||
|
||||
\hypersetup{
|
||||
colorlinks=true,
|
||||
linkcolor=blue,
|
||||
urlcolor=blue,
|
||||
pdfauthor={Студент},
|
||||
pdftitle={Лабораторная работа N2}
|
||||
}
|
||||
|
||||
\lstset{
|
||||
basicstyle=\ttfamily\footnotesize,
|
||||
keywordstyle=\color{blue},
|
||||
commentstyle=\color{green!60!black},
|
||||
stringstyle=\color{red},
|
||||
breaklines=true,
|
||||
frame=single,
|
||||
numbers=left,
|
||||
numberstyle=\tiny,
|
||||
tabsize=4,
|
||||
language=Python,
|
||||
extendedchars=true,
|
||||
inputencoding=utf8,
|
||||
}
|
||||
|
||||
\titleformat{\section}{\Large\bfseries\centering}{}{0pt}{}
|
||||
\titleformat{\subsection}{\large\bfseries}{}{0pt}{}
|
||||
\titleformat{\subsubsection}{\normalsize\bfseries}{}{0pt}{}
|
||||
|
||||
\renewcommand{\refname}{Список использованной литературы}
|
||||
|
||||
\begin{document}
|
||||
|
||||
% ============================================================================
|
||||
% ТИТУЛЬНЫЙ ЛИСТ
|
||||
% ============================================================================
|
||||
|
||||
\begin{titlepage}
|
||||
\begin{center}
|
||||
\vspace*{0.5cm}
|
||||
|
||||
{\Large \textbf{ФГБУ <<НМИЦ онкологии им. Н.Н. Блохина>> Минздрава России}}
|
||||
|
||||
\vspace{0.3cm}
|
||||
{\large Кафедра медицинской информатики и искусственного интеллекта}
|
||||
|
||||
\vspace{2.5cm}
|
||||
|
||||
{\Huge \textbf{ЛАБОРАТОРНАЯ РАБОТА №2}}
|
||||
|
||||
\vspace{0.5cm}
|
||||
{\huge \textbf{Анализ радиометрических признаков}}
|
||||
|
||||
\vspace{0.5cm}
|
||||
{\Large и построение модели обнаружения областей интереса}
|
||||
|
||||
\vspace{2.5cm}
|
||||
|
||||
\begin{tabular}{p{0.4\textwidth}p{0.4\textwidth}}
|
||||
\textbf{Выполнил:} & \textbf{Руководитель:} \\
|
||||
\underline{\hspace{4cm}} & \underline{\hspace{4cm}} \\
|
||||
\textit{ФИО студента} & \textit{ФИО преподавателя} \\
|
||||
Группа: \underline{\hspace{2cm}} & Учёная степень: \underline{\hspace{2cm}} \\
|
||||
Вариант: \underline{\hspace{2cm}} & \\
|
||||
\end{tabular}
|
||||
|
||||
\vspace{2.5cm}
|
||||
|
||||
{\large Москва, 2026}
|
||||
|
||||
\end{center}
|
||||
\end{titlepage}
|
||||
|
||||
% ============================================================================
|
||||
% СОДЕРЖАНИЕ
|
||||
% ============================================================================
|
||||
|
||||
\tableofcontents
|
||||
\newpage
|
||||
|
||||
% ============================================================================
|
||||
% 1. ВВЕДЕНИЕ
|
||||
% ============================================================================
|
||||
|
||||
\section{Введение}
|
||||
|
||||
\subsection{Цель работы}
|
||||
|
||||
Сформировать у слушателей практические навыки количественного анализа медицинских изображений методами радиомики и построения прогностических моделей машинного обучения для дифференциальной диагностики патологических образований.
|
||||
|
||||
\textbf{Задачи работы:}
|
||||
\begin{enumerate}
|
||||
\item Провести разведочный анализ данных (EDA) радиометрических признаков.
|
||||
\item Выполнить предобработку данных (импутация пропусков, масштабирование).
|
||||
\item Обучить модель бинарной классификации для дифференцировки патологических состояний.
|
||||
\item Оценить качество модели и интерпретировать результаты.
|
||||
\item Проанализировать важность радиометрических признаков для клинической задачи.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Клинический контекст}
|
||||
|
||||
В рамках лабораторной работы используются данные радиомического анализа пациентов с новообразованиями почек из датасета \texttt{1\_2236040\_zno\_cyst\_AF}. Задача состоит в построении модели, способной дифференцировать патологические образования (злокачественные опухоли, доброкачественные опухоли, кисты, абсцессы) на основе количественных признаков, извлечённых из медицинских изображений.
|
||||
|
||||
\textbf{Объекты дифференцировки:}
|
||||
\begin{itemize}
|
||||
\item Злокачественные опухоли (агрессивные новообразования)
|
||||
\item Доброкачественные опухоли и кисты (неагрессивные образования)
|
||||
\item Абсцессы (воспалительные процессы)
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Клиническая значимость:} Неинвазивная дифференцировка типов патологических образований почек на основе радиомических признаков позволяет:
|
||||
\begin{itemize}
|
||||
\item Снизить количество инвазивных диагностических процедур (биопсий).
|
||||
\item Ускорить процесс принятия клинических решений.
|
||||
\item Повысить точность дифференциальной диагностики.
|
||||
\item Персонализировать тактику лечения.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Концепция радиомики}
|
||||
|
||||
Радиомика — это высокопроизводительный метод извлечения количественных признаков из медицинских изображений (КТ, МРТ, ПЭТ). Её ключевая идея заключается в том, что визуальная информация содержит скрытые паттерны, неразличимые для человеческого глаза, но поддающиеся математическому описанию. Эти паттерны могут служить неинвазивными биомаркерами, отражающими гистологию, генетику и агрессивность заболевания.
|
||||
|
||||
\textbf{Пайплайн радиомического анализа:}
|
||||
\begin{enumerate}
|
||||
\item Получение медицинских изображений (КТ, МРТ).
|
||||
\item Сегментация областей интереса (ROI).
|
||||
\item Извлечение количественных признаков.
|
||||
\item Предобработка и отбор признаков.
|
||||
\item Построение прогностических моделей.
|
||||
\item Клиническая валидация и интерпретация.
|
||||
\end{enumerate}
|
||||
|
||||
% ============================================================================
|
||||
% 2. ТЕОРЕТИЧЕСКАЯ ЧАСТЬ
|
||||
% ============================================================================
|
||||
|
||||
\section{Теоретическая часть}
|
||||
|
||||
\subsection{Классификация радиометрических признаков}
|
||||
|
||||
Современные библиотеки (например, PyRadiomics) извлекают более 100 признаков. Они делятся на несколько основных групп.
|
||||
|
||||
\subsubsection{Геометрические признаки (Shape)}
|
||||
|
||||
Описывают форму и размер области интереса (ROI).
|
||||
|
||||
\textbf{Элонгация (вытянутость):}
|
||||
\begin{equation}
|
||||
E = \frac{L_{minor}}{L_{major}}
|
||||
\end{equation}
|
||||
где:
|
||||
\begin{itemize}
|
||||
\item $E$ -- элонгация (от 0 до 1)
|
||||
\item $L_{minor}$ и $L_{major}$ -- малая и большая оси аппроксимирующего эллипса
|
||||
\end{itemize}
|
||||
Значение, близкое к 1, указывает на округлую (часто доброкачественную) форму.
|
||||
|
||||
\textbf{Сферичность:}
|
||||
\begin{equation}
|
||||
S = \frac{36\pi V^2}{A^3}
|
||||
\end{equation}
|
||||
где:
|
||||
\begin{itemize}
|
||||
\item $V$ -- объём ROI
|
||||
\item $A$ -- площадь поверхности
|
||||
\end{itemize}
|
||||
Низкая сферичность указывает на инфильтративный, нерегулярный рост.
|
||||
|
||||
\subsubsection{Статистики первого порядка (First-order)}
|
||||
|
||||
Описывают распределение интенсивности пикселей без учёта их расположения.
|
||||
|
||||
\textbf{Среднее значение:}
|
||||
\begin{equation}
|
||||
\mu = \frac{1}{N} \sum_{i=1}^{N} X_i
|
||||
\end{equation}
|
||||
где:
|
||||
\begin{itemize}
|
||||
\item $\mu$ -- средняя интенсивность
|
||||
\item $N$ -- число пикселей в маске
|
||||
\item $X_i$ -- интенсивность $i$-го пикселя
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Дисперсия:}
|
||||
\begin{equation}
|
||||
\sigma^2 = \frac{1}{N-1} \sum_{i=1}^{N} (X_i - \mu)^2
|
||||
\end{equation}
|
||||
где $\sigma^2$ -- мера разброса значений (неоднородности ткани).
|
||||
|
||||
\textbf{Энтропия (мера хаотичности):}
|
||||
\begin{equation}
|
||||
H = -\sum_{k} p_k \cdot \log_2(p_k)
|
||||
\end{equation}
|
||||
где:
|
||||
\begin{itemize}
|
||||
\item $H$ -- энтропия Шеннона
|
||||
\item $p_k$ -- вероятность появления интенсивности $k$
|
||||
\end{itemize}
|
||||
Высокая энтропия часто коррелирует с некрозом или фиброзом внутри опухоли.
|
||||
|
||||
\subsubsection{Текстурные признаки}
|
||||
|
||||
\textbf{Матрица пространственной смежности (GLCM)} оценивает, как часто пиксели с определёнными уровнями яркости встречаются рядом.
|
||||
|
||||
\textbf{Контраст:}
|
||||
\begin{equation}
|
||||
Contrast = \sum_{i} \sum_{j} |i - j|^2 \cdot P(i, j)
|
||||
\end{equation}
|
||||
где $P(i, j)$ -- вероятность совместного появления пикселей с интенсивностями $i$ и $j$. Высокий контраст указывает на резкие перепады яркости.
|
||||
|
||||
\textbf{Энергия (однородность):}
|
||||
\begin{equation}
|
||||
Energy = \sum_{i} \sum_{j} P(i, j)^2
|
||||
\end{equation}
|
||||
Высокая энергия указывает на однородность текстуры.
|
||||
|
||||
\textbf{Корреляция:}
|
||||
\begin{equation}
|
||||
Correlation = \frac{\sum_{i} \sum_{j} (i - \mu_i)(j - \mu_j) P(i, j)}{\sigma_i \sigma_j}
|
||||
\end{equation}
|
||||
Характеризует линейную зависимость между соседними пикселями.
|
||||
|
||||
\subsection{Метрики оценки моделей в клиническом контексте}
|
||||
|
||||
При бинарной классификации ($0$ -- норма/доброкачественное, $1$ -- патология/злокачественное) критически важен выбор метрики.
|
||||
|
||||
\textbf{Полнота (Recall):}
|
||||
\begin{equation}
|
||||
Recall = \frac{TP}{TP + FN}
|
||||
\end{equation}
|
||||
Приоритетна для скрининга: минимизирует пропуск патологии (ложноотрицательные результаты).
|
||||
|
||||
\textbf{Точность (Precision):}
|
||||
\begin{equation}
|
||||
Precision = \frac{TP}{TP + FP}
|
||||
\end{equation}
|
||||
Приоритетна для подтверждающей диагностики: минимизирует ложные тревоги, ведущие к ненужным биопсиям.
|
||||
|
||||
\textbf{F1-мера (баланс):}
|
||||
\begin{equation}
|
||||
F1 = 2 \cdot \frac{Precision \cdot Recall}{Precision + Recall}
|
||||
\end{equation}
|
||||
|
||||
\textbf{ROC-AUC:} Площадь под ROC-кривой. Значение 0.5 соответствует случайному угадыванию, 1.0 -- идеальному классификатору.
|
||||
|
||||
\subsection{Предобработка данных}
|
||||
|
||||
\textbf{Стандартизация (Z-score):}
|
||||
\begin{equation}
|
||||
z = \frac{x - \mu}{\sigma}
|
||||
\end{equation}
|
||||
где:
|
||||
\begin{itemize}
|
||||
\item $z$ -- нормализованное значение
|
||||
\item $x$ -- исходное значение
|
||||
\item $\mu$ и $\sigma$ -- среднее и стандартное отклонение признака по обучающей выборке
|
||||
\end{itemize}
|
||||
Обязательна для линейных моделей и нейросетей.
|
||||
|
||||
\textbf{Импутация пропусков:}
|
||||
\begin{equation}
|
||||
x_{imputed} = \text{median}(X)
|
||||
\end{equation}
|
||||
Медианная импутация устойчива к выбросам.
|
||||
|
||||
% ============================================================================
|
||||
% 3. ПРАКТИЧЕСКАЯ ЧАСТЬ
|
||||
% ============================================================================
|
||||
|
||||
\section{Практическая часть}
|
||||
|
||||
\subsection{Загрузка и разведочный анализ данных (EDA)}
|
||||
|
||||
\subsubsection{Загрузка данных}
|
||||
|
||||
Радиометрические характеристики сохраняются в CSV-формате после обработки на платформе <<БиоМедАналитика>>.
|
||||
|
||||
\begin{lstlisting}
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import seaborn as sns
|
||||
|
||||
df = pd.read_csv('result.csv')
|
||||
print(df.shape)
|
||||
print(df.columns.tolist()[:10])
|
||||
print(df.info())
|
||||
print(df.describe())
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Анализ распределения классов}
|
||||
|
||||
\begin{lstlisting}
|
||||
print("Distribution of classes:")
|
||||
print(df['label'].value_counts())
|
||||
print(df['label'].value_counts(normalize=True))
|
||||
|
||||
sns.countplot(data=df, x='label')
|
||||
plt.title('Distribution of classes')
|
||||
plt.show()
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Визуализация распределений признаков}
|
||||
|
||||
\begin{lstlisting}
|
||||
features = ['original_firstorder_Mean', 'original_firstorder_Entropy',
|
||||
'original_glcm_Contrast', 'original_glcm_Correlation']
|
||||
|
||||
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
|
||||
for i, feat in enumerate(features):
|
||||
ax = axes[i//2, i%2]
|
||||
sns.histplot(data=df, x=feat, hue='label', kde=True, ax=ax)
|
||||
ax.set_title(feat)
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Предобработка данных}
|
||||
|
||||
\subsubsection{Выделение признаков и целевой переменной}
|
||||
|
||||
\begin{lstlisting}
|
||||
feature_cols = [col for col in df.columns if col not in ['label', 'path_to_cell', 'source_file']]
|
||||
X = df[feature_cols]
|
||||
y = df['label']
|
||||
|
||||
print("Features shape:", X.shape)
|
||||
print("Target shape:", y.shape)
|
||||
print("Classes:", y.unique())
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Разделение на обучающую и тестовую выборки}
|
||||
|
||||
\begin{lstlisting}
|
||||
from sklearn.model_selection import train_test_split
|
||||
|
||||
X_train, X_test, y_train, y_test = train_test_split(
|
||||
X, y, test_size=0.3, random_state=42, stratify=y
|
||||
)
|
||||
|
||||
print("Train size:", X_train.shape[0])
|
||||
print("Test size:", X_test.shape[0])
|
||||
print("Train class distribution:\n", y_train.value_counts(normalize=True))
|
||||
print("Test class distribution:\n", y_test.value_counts(normalize=True))
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Импутация пропусков}
|
||||
|
||||
\begin{lstlisting}
|
||||
from sklearn.impute import SimpleImputer
|
||||
|
||||
imputer = SimpleImputer(strategy='median')
|
||||
X_train_imputed = imputer.fit_transform(X_train)
|
||||
X_test_imputed = imputer.transform(X_test)
|
||||
|
||||
print("Missing values after imputation:",
|
||||
np.isnan(X_train_imputed).sum(), np.isnan(X_test_imputed).sum())
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Стандартизация}
|
||||
|
||||
\begin{lstlisting}
|
||||
from sklearn.preprocessing import StandardScaler
|
||||
|
||||
scaler = StandardScaler()
|
||||
X_train_scaled = scaler.fit_transform(X_train_imputed)
|
||||
X_test_scaled = scaler.transform(X_test_imputed)
|
||||
|
||||
print("Mean after scaling:", X_train_scaled.mean(axis=0)[:5])
|
||||
print("Std after scaling:", X_train_scaled.std(axis=0)[:5])
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Обучение модели}
|
||||
|
||||
\subsubsection{Случайный лес (Random Forest)}
|
||||
|
||||
Случайный лес устойчив к выбросам, не требует строгой нормализации и позволяет оценить важность признаков.
|
||||
|
||||
\begin{lstlisting}
|
||||
from sklearn.ensemble import RandomForestClassifier
|
||||
from sklearn.metrics import classification_report, confusion_matrix
|
||||
from sklearn.metrics import roc_auc_score, RocCurveDisplay
|
||||
|
||||
model = RandomForestClassifier(
|
||||
n_estimators=100,
|
||||
random_state=42,
|
||||
class_weight='balanced'
|
||||
)
|
||||
|
||||
model.fit(X_train_scaled, y_train)
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Оценка качества}
|
||||
|
||||
\begin{lstlisting}
|
||||
y_pred = model.predict(X_test_scaled)
|
||||
y_prob = model.predict_proba(X_test_scaled)[:, 1]
|
||||
|
||||
print("Classification Report:")
|
||||
print(classification_report(y_test, y_pred, target_names=['Benign', 'Malignant']))
|
||||
|
||||
cm = confusion_matrix(y_test, y_pred)
|
||||
print("Confusion Matrix:")
|
||||
print(cm)
|
||||
|
||||
auc = roc_auc_score(y_test, y_prob)
|
||||
print("ROC-AUC:", auc)
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Визуализация результатов}
|
||||
|
||||
\begin{lstlisting}
|
||||
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
|
||||
|
||||
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=axes[0])
|
||||
axes[0].set_title('Confusion Matrix')
|
||||
axes[0].set_xlabel('Predicted')
|
||||
axes[0].set_ylabel('True')
|
||||
|
||||
RocCurveDisplay.from_estimator(model, X_test_scaled, y_test, ax=axes[1])
|
||||
axes[1].set_title('ROC Curve')
|
||||
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Анализ важности признаков}
|
||||
|
||||
\begin{lstlisting}
|
||||
importance = pd.DataFrame({
|
||||
'feature': feature_cols,
|
||||
'importance': model.feature_importances_
|
||||
}).sort_values('importance', ascending=False)
|
||||
|
||||
print("Top 10 features:")
|
||||
print(importance.head(10))
|
||||
|
||||
plt.figure(figsize=(10, 8))
|
||||
sns.barplot(data=importance.head(15), x='importance', y='feature')
|
||||
plt.title('Feature Importance')
|
||||
plt.xlabel('Importance')
|
||||
plt.tight_layout()
|
||||
plt.show()
|
||||
\end{lstlisting}
|
||||
|
||||
% ============================================================================
|
||||
% 4. ВАРИАНТЫ ЗАДАНИЙ
|
||||
% ============================================================================
|
||||
|
||||
\section{Варианты заданий}
|
||||
|
||||
Выберите один из вариантов в соответствии с указанием преподавателя. Каждый вариант акцентирует внимание на специфике определённой анатомической зоны.
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Варианты заданий}
|
||||
\begin{tabular}{p{1.5cm}|p{5cm}|p{6cm}}
|
||||
\toprule
|
||||
\textbf{Вариант} & \textbf{Анатомическая зона} & \textbf{Акцент} \\
|
||||
\midrule
|
||||
1 & Почки & Геометрические признаки и статистики первого порядка \\
|
||||
2 & Молочная железа & Текстурные признаки (GLCM, GLRLM) \\
|
||||
3 & Головной мозг & Спектральные признаки и NGTDM \\
|
||||
4 & Брюшная полость & Комбинированное использование всех групп признаков \\
|
||||
5 & Мультимодальный анализ & Сравнительный анализ и формулировка гипотез \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\textbf{Задание повышенной сложности (со звёздочкой):}
|
||||
|
||||
Реализуйте отбор признаков методом рекурсивного исключения (RFE) или через \texttt{SelectFromModel}. Сравните метрики модели до и после уменьшения размерности.
|
||||
|
||||
\begin{lstlisting}
|
||||
from sklearn.feature_selection import RFE
|
||||
from sklearn.linear_model import LogisticRegression
|
||||
|
||||
selector = RFE(LogisticRegression(), n_features_to_select=20)
|
||||
selector.fit(X_train_scaled, y_train)
|
||||
selected_features = selector.get_support()
|
||||
|
||||
print("Selected features:", np.sum(selected_features))
|
||||
X_train_selected = X_train_scaled[:, selected_features]
|
||||
X_test_selected = X_test_scaled[:, selected_features]
|
||||
|
||||
model_selected = RandomForestClassifier(random_state=42)
|
||||
model_selected.fit(X_train_selected, y_train)
|
||||
y_pred_selected = model_selected.predict(X_test_selected)
|
||||
|
||||
print("Accuracy with RFE:", accuracy_score(y_test, y_pred_selected))
|
||||
\end{lstlisting}
|
||||
|
||||
% ============================================================================
|
||||
% 5. РЕЗУЛЬТАТЫ
|
||||
% ============================================================================
|
||||
|
||||
\section{Результаты}
|
||||
|
||||
\subsection{Пример результатов}
|
||||
|
||||
Ниже приведены типичные результаты, которые можно получить при выполнении работы.
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Метрики качества модели (пример)}
|
||||
\begin{tabular}{l|r|r|r}
|
||||
\toprule
|
||||
\textbf{Метрика} & \textbf{Значение} & \textbf{95\% CI} & \textbf{Интерпретация} \\
|
||||
\midrule
|
||||
Accuracy & 0.89 & 0.85--0.93 & Хорошее качество \\
|
||||
Precision (Malignant) & 0.87 & 0.82--0.92 & Низкий уровень ЛП \\
|
||||
Recall (Malignant) & 0.92 & 0.88--0.96 & Высокая чувствительность \\
|
||||
F1 (Malignant) & 0.89 & 0.85--0.93 & Хороший баланс \\
|
||||
ROC-AUC & 0.94 & 0.91--0.97 & Отличная дискриминация \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{Важность признаков (пример)}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Топ-10 важнейших признаков}
|
||||
\begin{tabular}{l|r}
|
||||
\toprule
|
||||
\textbf{Признак} & \textbf{Важность} \\
|
||||
\midrule
|
||||
original\_firstorder\_Entropy & 0.142 \\
|
||||
original\_glcm\_Contrast & 0.118 \\
|
||||
original\_firstorder\_Variance & 0.095 \\
|
||||
original\_shape\_Sphericity & 0.087 \\
|
||||
original\_glcm\_Correlation & 0.076 \\
|
||||
original\_firstorder\_Mean & 0.068 \\
|
||||
original\_glrlm\_RunEntropy & 0.062 \\
|
||||
original\_glszm\_ZoneEntropy & 0.055 \\
|
||||
original\_gldm\_DependenceEntropy & 0.048 \\
|
||||
original\_shape\_Elongation & 0.041 \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\textbf{Интерпретация:}
|
||||
\begin{enumerate}
|
||||
\item \textbf{Энтропия} (original\_firstorder\_Entropy) -- отражает гетерогенность ткани. Высокая энтропия указывает на неоднородность, характерную для злокачественных образований.
|
||||
\item \textbf{Контраст} (original\_glcm\_Contrast) -- характеризует резкие перепады интенсивности, связанные с неоваскуляризацией и некрозом.
|
||||
\item \textbf{Дисперсия} (original\_firstorder\_Variance) -- мера разброса значений интенсивности, отражающая неоднородность ткани.
|
||||
\item \textbf{Сферичность} (original\_shape\_Sphericity) -- низкая сферичность характерна для инфильтративного роста злокачественных опухолей.
|
||||
\end{enumerate}
|
||||
|
||||
% ============================================================================
|
||||
% 6. ВЫВОДЫ
|
||||
% ============================================================================
|
||||
|
||||
\section{Выводы}
|
||||
|
||||
В ходе выполнения лабораторной работы были получены следующие результаты:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Проведён разведочный анализ данных}: выявлены закономерности в распределении признаков, определены классы и их соотношение.
|
||||
|
||||
\item \textbf{Выполнена предобработка данных}: реализована импутация пропусков и стандартизация признаков.
|
||||
|
||||
\item \textbf{Обучена модель случайного леса}: модель демонстрирует высокое качество классификации (ROC-AUC $> 0.9$).
|
||||
|
||||
\item \textbf{Проведён анализ важности признаков}: выявлены ключевые радиометрические характеристики (энтропия, контраст, дисперсия, сферичность) для дифференцировки патологических состояний.
|
||||
|
||||
\item \textbf{Результаты интерпретированы с клинической точки зрения}: подтверждена диагностическая ценность текстурных признаков и статистик первого порядка.
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Клинические рекомендации:}
|
||||
\begin{enumerate}
|
||||
\item Для скрининга рекомендуется использовать метрику Recall (минимизация пропуска патологии).
|
||||
\item Для подтверждающей диагностики рекомендуется использовать метрику Precision (минимизация ложных тревог).
|
||||
\item Текстурные признаки (GLCM\_Contrast, GLCM\_Entropy) являются наиболее информативными для дифференциальной диагностики.
|
||||
\end{enumerate}
|
||||
|
||||
% ============================================================================
|
||||
% 7. КОНТРОЛЬНЫЕ ВОПРОСЫ
|
||||
% ============================================================================
|
||||
|
||||
\section{Контрольные вопросы}
|
||||
|
||||
\begin{enumerate}
|
||||
\item В чём заключается принципиальное различие между статистиками первого порядка и текстурными признаками? Приведите пример медицинской задачи, в которой каждый из этих типов признаков будет обладать максимальной диагностической ценностью.
|
||||
|
||||
\item Почему метрика Accuracy может давать искажённое представление о качестве модели при работе с медицинскими данными? Какие альтернативные метрики предпочтительнее использовать в задачах скрининга и по какой причине?
|
||||
|
||||
\item Какую информацию несёт коэффициент корреляции Пирсона между двумя признаками? Почему наличие сильной корреляции (мультиколлинеарности) может создавать проблемы при обучении линейных моделей?
|
||||
|
||||
\item Дайте содержательное объяснение метрики ROC-AUC. В каких ситуациях её использование более оправдано по сравнению с F1-мерой?
|
||||
|
||||
\item Перечислите обязательные этапы предобработки радиометрических данных перед обучением модели. Обоснуйте необходимость каждого из них с точки зрения статистики и машинного обучения.
|
||||
|
||||
\item Проанализируйте матрицу ошибок вашей модели: какое количество ложноположительных и ложноотрицательных прогнозов было допущено? Какой из этих типов ошибок представляет большую опасность в контексте вашей задачи и почему?
|
||||
|
||||
\item Назовите три признака, оказавшие наибольшее влияние на прогноз вашей модели. Как вы интерпретируете их вклад с медицинской точки зрения?
|
||||
|
||||
\item Если бы у вас появилась возможность дополнить набор данных одним новым типом информации (помимо радиометрических признаков), что бы вы выбрали: клинические метаданные, результаты лабораторных исследований, геномные данные? Обоснуйте свой выбор.
|
||||
|
||||
\item Как изменится ваша стратегия моделирования при увеличении объёма обучающей выборки в десять раз? Какие корректировки потребуются в случае сокращения данных вдвое?
|
||||
|
||||
\item Какие шаги вы предпримете, если модель демонстрирует высокую полноту при низкой точности прогноза положительных случаев (или наоборот)? Как такой дисбаланс повлияет на возможности клинического применения модели?
|
||||
\end{enumerate}
|
||||
|
||||
% ============================================================================
|
||||
% 8. СПИСОК ЛИТЕРАТУРЫ
|
||||
% ============================================================================
|
||||
|
||||
\section{Список литературы}
|
||||
|
||||
\begin{enumerate}
|
||||
\item Владзимирский, А. В. Компьютерное зрение в лучевой диагностике: первый этап Московского эксперимента / А. В. Владзимирский, Ю. А. Васильев, К. М. Арзамасов [и др.]. -- 2-е изд. -- Москва : ООО <<Издательские решения>>, 2023. -- 388 с. -- ISBN 978-5-0059-3043-9.
|
||||
|
||||
\item Гавриченков, Ю. Д. Системы искусственного интеллекта : учебно-методическое пособие / Ю. Д. Гавриченков, В. Ю. Переверзев. -- Самара : Медицинский университет <<Реавиз>>, 2024. -- 55 с.
|
||||
|
||||
\item Поляков, Е. В. Цифровая обработка медицинских изображений : учебное пособие / Е. В. Поляков, В. В. Дмитриева, А. А. Фроня. -- Москва : НИЯУ МИФИ, 2024. -- 100 с.
|
||||
|
||||
\item Савченко, Е. Ю. Основы и применение нейронных сетей: теория, практика, инновации : учебное пособие / Е. Ю. Савченко. -- Бишкек : Нео Принт, 2024. -- 116 с.
|
||||
|
||||
\item van Griethuysen, J. J. M. Computational Radiomics System to Decode the Radiographic Phenotype / J. J. M. van Griethuysen, A. Fedorov, C. Parmar [et al.] // Cancer Research. -- 2017. -- Vol. 77, No. 21. -- P. e104--e107.
|
||||
|
||||
\item Lambin, P. Radiomics: the bridge between medical imaging and personalized medicine / P. Lambin, E. Rios-Velazquez, R. Leijenaar [et al.] // Nature Reviews Clinical Oncology. -- 2017. -- Vol. 14, No. 12. -- P. 749--762.
|
||||
|
||||
\item Breiman, L. Random Forests / L. Breiman // Machine Learning. -- 2001. -- Vol. 45, No. 1. -- P. 5--32.
|
||||
\end{enumerate}
|
||||
|
||||
\end{document}
|
||||
LFS
BIN
Binary file not shown.
+1064
File diff suppressed because it is too large
Load Diff
LFS
BIN
Binary file not shown.
+868
@@ -0,0 +1,868 @@
|
||||
% ============================================================================
|
||||
% ЛАБОРАТОРНАЯ РАБОТА №4
|
||||
% ПОЛНЫЙ ПАЙПЛАЙН ПОДГОТОВКИ ДАННЫХ И ОБУЧЕНИЯ МОДЕЛЕЙ ИИ
|
||||
% ============================================================================
|
||||
|
||||
\documentclass[12pt,a4paper]{article}
|
||||
|
||||
% ============================================================================
|
||||
% ПРЕАМБУЛА
|
||||
% ============================================================================
|
||||
|
||||
\usepackage[utf8]{inputenc}
|
||||
\usepackage[T2A]{fontenc}
|
||||
\usepackage[russian]{babel}
|
||||
|
||||
\usepackage{amsmath,amssymb,amsfonts}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{hyperref}
|
||||
\usepackage{listings}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{geometry}
|
||||
\usepackage{booktabs}
|
||||
\usepackage{longtable}
|
||||
\usepackage{caption}
|
||||
\usepackage{subcaption}
|
||||
\usepackage{titlesec}
|
||||
\usepackage{float}
|
||||
\usepackage{array}
|
||||
\usepackage{multirow}
|
||||
\usepackage{enumitem}
|
||||
\usepackage{setspace}
|
||||
|
||||
\geometry{left=2.5cm,right=2cm,top=2cm,bottom=2cm}
|
||||
|
||||
\hypersetup{
|
||||
colorlinks=true,
|
||||
linkcolor=blue,
|
||||
urlcolor=blue,
|
||||
pdfauthor={Student},
|
||||
pdftitle={Lab 4}
|
||||
}
|
||||
|
||||
% --- НАСТРОЙКА ЛИСТИНГОВ С ПОДДЕРЖКОЙ КИРИЛЛИЦЫ ---
|
||||
\lstset{
|
||||
breaklines=true,
|
||||
breakatwhitespace=false,
|
||||
basicstyle=\scriptsize\ttfamily,
|
||||
keywordstyle=\bfseries\color{blue!70},
|
||||
commentstyle=\itshape\color{gray!70},
|
||||
stringstyle=\color{red!60!black},
|
||||
frame=single,
|
||||
rulecolor=\color{gray!50},
|
||||
numbers=left,
|
||||
numberstyle=\tiny\color{gray},
|
||||
numbersep=5pt,
|
||||
tabsize=4,
|
||||
showstringspaces=false,
|
||||
captionpos=b,
|
||||
extendedchars=true,
|
||||
literate=
|
||||
{А}{{\selectfont\char192}}1 {Б}{{\selectfont\char193}}1 {В}{{\selectfont\char194}}1 {Г}{{\selectfont\char195}}1 {Д}{{\selectfont\char196}}1 {Е}{{\selectfont\char197}}1 {Ё}{{\selectfont\char168}}1 {Ж}{{\selectfont\char198}}1 {З}{{\selectfont\char199}}1 {И}{{\selectfont\char200}}1 {Й}{{\selectfont\char201}}1 {К}{{\selectfont\char202}}1 {Л}{{\selectfont\char203}}1 {М}{{\selectfont\char204}}1 {Н}{{\selectfont\char205}}1 {О}{{\selectfont\char206}}1 {П}{{\selectfont\char207}}1 {Р}{{\selectfont\char208}}1 {С}{{\selectfont\char209}}1 {Т}{{\selectfont\char210}}1 {У}{{\selectfont\char211}}1 {Ф}{{\selectfont\char212}}1 {Х}{{\selectfont\char213}}1 {Ц}{{\selectfont\char214}}1 {Ч}{{\selectfont\char215}}1 {Ш}{{\selectfont\char216}}1 {Щ}{{\selectfont\char217}}1 {Ъ}{{\selectfont\char218}}1 {Ы}{{\selectfont\char219}}1 {Ь}{{\selectfont\char220}}1 {Э}{{\selectfont\char221}}1 {Ю}{{\selectfont\char222}}1 {Я}{{\selectfont\char223}}1
|
||||
{а}{{\selectfont\char224}}1 {б}{{\selectfont\char225}}1 {в}{{\selectfont\char226}}1 {г}{{\selectfont\char227}}1 {д}{{\selectfont\char228}}1 {е}{{\selectfont\char229}}1 {ё}{{\selectfont\char184}}1 {ж}{{\selectfont\char230}}1 {з}{{\selectfont\char231}}1 {и}{{\selectfont\char232}}1 {й}{{\selectfont\char233}}1 {к}{{\selectfont\char234}}1 {л}{{\selectfont\char235}}1 {м}{{\selectfont\char236}}1 {н}{{\selectfont\char237}}1 {о}{{\selectfont\char238}}1 {п}{{\selectfont\char239}}1 {р}{{\selectfont\char240}}1 {с}{{\selectfont\char241}}1 {т}{{\selectfont\char242}}1 {у}{{\selectfont\char243}}1 {ф}{{\selectfont\char244}}1 {х}{{\selectfont\char245}}1 {ц}{{\selectfont\char246}}1 {ч}{{\selectfont\char247}}1 {ш}{{\selectfont\char248}}1 {щ}{{\selectfont\char249}}1 {ъ}{{\selectfont\char250}}1 {ы}{{\selectfont\char251}}1 {ь}{{\selectfont\char252}}1 {э}{{\selectfont\char253}}1 {ю}{{\selectfont\char254}}1 {я}{{\selectfont\char255}}1
|
||||
}
|
||||
|
||||
\titleformat{\section}{\Large\bfseries\centering}{}{0pt}{}
|
||||
\titleformat{\subsection}{\large\bfseries}{}{0pt}{}
|
||||
\titleformat{\subsubsection}{\normalsize\bfseries}{}{0pt}{}
|
||||
|
||||
\renewcommand{\refname}{References}
|
||||
|
||||
\begin{document}
|
||||
|
||||
% ============================================================================
|
||||
% ТИТУЛЬНЫЙ ЛИСТ
|
||||
% ============================================================================
|
||||
|
||||
\begin{titlepage}
|
||||
\begin{center}
|
||||
\vspace*{0.5cm}
|
||||
|
||||
{\Large \textbf{ФГБУ <<НМИЦ онкологии им. Н.Н. Блохина>> Минздрава России}}
|
||||
|
||||
\vspace{0.3cm}
|
||||
{\large Кафедра медицинской информатики и искусственного интеллекта}
|
||||
|
||||
\vspace{2.5cm}
|
||||
|
||||
{\Huge \textbf{ЛАБОРАТОРНАЯ РАБОТА №4}}
|
||||
|
||||
\vspace{0.5cm}
|
||||
{\huge \textbf{Полный пайплайн подготовки данных}}
|
||||
|
||||
\vspace{0.5cm}
|
||||
{\Large и обучения моделей искусственного интеллекта в онкологии}
|
||||
|
||||
\vspace{0.5cm}
|
||||
{\Large \textbf{От сырых медицинских данных до готовой модели}}
|
||||
|
||||
\vspace{2.5cm}
|
||||
|
||||
\begin{tabular}{p{0.4\textwidth} p{0.4\textwidth}}
|
||||
\textbf{Выполнил:} & \textbf{Руководитель:} \\
|
||||
\underline{\hspace{4cm}} & \underline{\hspace{4cm}} \\
|
||||
\textit{ФИО студента} & \textit{ФИО преподавателя} \\
|
||||
Группа: \underline{\hspace{2cm}} & Учёная степень: \underline{\hspace{2cm}} \\
|
||||
Вариант: \underline{\hspace{2cm}} & \\
|
||||
\end{tabular}
|
||||
|
||||
\vspace{2.5cm}
|
||||
|
||||
{\large Москва, 2026}
|
||||
|
||||
\end{center}
|
||||
\end{titlepage}
|
||||
|
||||
% ============================================================================
|
||||
% СОДЕРЖАНИЕ
|
||||
% ============================================================================
|
||||
|
||||
\tableofcontents
|
||||
\newpage
|
||||
|
||||
% ============================================================================
|
||||
% ВВЕДЕНИЕ
|
||||
% ============================================================================
|
||||
|
||||
\section{Введение}
|
||||
|
||||
\subsection{Цель работы}
|
||||
|
||||
Систематизировать и интегрировать знания, полученные в ходе выполнения предыдущих лабораторных работ, в единый производственный пайплайн обработки медицинских данных для задач искусственного интеллекта в онкологии. Сформировать целостное понимание всех этапов: от получения сырых медицинских данных до развёртывания обученной модели в клинической практике.
|
||||
|
||||
\textbf{Задачи работы:}
|
||||
\begin{enumerate}
|
||||
\item Проанализировать полный жизненный цикл данных в проекте медицинского ИИ.
|
||||
\item Рассмотреть все этапы пайплайна: сбор, аудит, предобработка, разметка, обучение, валидация, внедрение.
|
||||
\item Изучить работу скриптов и инструментов, обеспечивающих автоматизацию процессов.
|
||||
\item Разобрать практические примеры и типичные ошибки на каждом этапе.
|
||||
\item Сформулировать рекомендации по организации производственного процесса.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Место работы в общем курсе}
|
||||
|
||||
Лабораторная работа №4 является \textbf{интегрирующей} и \textbf{обобщающей}. Она объединяет знания из трёх предыдущих работ:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{ЛР №1}: Аудит и подготовка медицинских данных (форматы DICOM, NRRD, конвертация).
|
||||
\item \textbf{ЛР №2}: Анализ радиометрических признаков (извлечение, предобработка, моделирование).
|
||||
\item \textbf{ЛР №3}: Радиомический анализ опухолей мозга (BRATS, мультипараметрическая МРТ).
|
||||
\end{itemize}
|
||||
|
||||
В четвёртой работе рассматриваются:
|
||||
\begin{itemize}
|
||||
\item Организация проекта и работа с репозиторием.
|
||||
\item Автоматизация пайплайна с помощью скриптов.
|
||||
\item Интеграция всех этапов в единый процесс.
|
||||
\item Клиническая валидация и внедрение моделей.
|
||||
\item Поддержка и мониторинг моделей в эксплуатации.
|
||||
\end{itemize}
|
||||
|
||||
% ============================================================================
|
||||
% ГЛАВА 1. ОРГАНИЗАЦИЯ ПРОЕКТА
|
||||
% ============================================================================
|
||||
|
||||
\section{Организация проекта}
|
||||
|
||||
\subsection{Структура репозитория}
|
||||
|
||||
Правильная организация проекта — основа успешной работы. Репозиторий имеет следующую структуру:
|
||||
|
||||
\begin{verbatim}
|
||||
ai-med-edu/
|
||||
|
|
||||
|-- README.md # Документация проекта
|
||||
|-- ai-use-program.doc # Учебная программа
|
||||
|-- references.txt # Список литературы
|
||||
|
|
||||
|-- data/ # Экспериментальные данные
|
||||
| |-- 1_2236040_zno_cyst_AF/ # Эксперимент 1 (ZNO Cyst AF)
|
||||
| | |-- predefined_classes.txt # Схема классов (12 классов)
|
||||
| | |-- data.yaml # Конфиг YOLO
|
||||
| | |-- *.nrrd # Исходные 3D данные
|
||||
| | |-- dcm/ # DICOM-срезы (1042 файла)
|
||||
| | |-- images/ # PNG-срезы (300 файлов)
|
||||
| | |-- images_labels/ # Bbox-разметка
|
||||
| | | |-- polygons/ # Полигоны для сегментации
|
||||
| | |-- images_result/ # Визуализация результатов
|
||||
| | |-- masks_sam/ # Бинарные маски
|
||||
| |
|
||||
| |-- prep/ # Подготовительные данные
|
||||
| | |-- predefined_classes.txt
|
||||
| | |-- csv/ # CSV-файлы с разметкой
|
||||
| | |-- images/ # DCM и JPG файлы
|
||||
| | |-- images_labels/ # TXT-лейблы
|
||||
| | |-- images_results/ # Результаты
|
||||
| |
|
||||
| |-- example/ # Шаблон структуры
|
||||
|
|
||||
|-- scripts/ # Скрипты
|
||||
| |-- ttv_freq2.py # Стратифицированный сплиттер
|
||||
| |-- train_yolo.py # Обучение детекции
|
||||
| |-- train_yolo_seg.py # Обучение сегментации
|
||||
| |-- check_PyTorch_gpu.py # Проверка GPU
|
||||
| |-- check_tf_gpu.py # Проверка TensorFlow GPU
|
||||
| |-- config/ # Конфигурации
|
||||
| | |-- data.yaml
|
||||
| |-- Тема 2.1/ # 3D радиомика
|
||||
| | |-- analysis.py
|
||||
| | |-- config_3d.py
|
||||
| | |-- feature_3d.py
|
||||
| | |-- segmentation.py
|
||||
| |-- Тема 2.2/ # Конвертация NRRD
|
||||
| |-- nrrd_to_yolo.py
|
||||
|
|
||||
|-- env/ # Виртуальное окружение
|
||||
| |-- Include/
|
||||
| |-- Lib/
|
||||
| | |-- site-packages/ # Установленные пакеты
|
||||
| |-- Scripts/ # Исполняемые файлы
|
||||
| |-- pyvenv.cfg
|
||||
|
|
||||
|-- lectures/ # Лекционные материалы
|
||||
| |-- К26_1_1.pdf
|
||||
| |-- К26_2_1.pdf
|
||||
| |-- К26_2_2.pdf
|
||||
|
|
||||
|-- seminars/ # Семинарские занятия
|
||||
| |-- FeatureExtractionClient.ipynb
|
||||
| |-- Тема 1.1/
|
||||
| | |-- Dataset.ipynb
|
||||
| | |-- Noise.ipynb
|
||||
| | |-- Resource1.ipynb
|
||||
| | |-- resource2.ipynb
|
||||
| | |-- segm2.ipynb
|
||||
| |-- Тема 1.2/
|
||||
| | |-- Практикум1.ipynb
|
||||
| | |-- Т1.ipynb
|
||||
| | |-- Т2.ipynb
|
||||
| | |-- best_spleen_model.pth
|
||||
| |-- Тема 2.1/
|
||||
| | |-- radiomics_report.html
|
||||
| | |-- segmentation_full_report.html
|
||||
| | |-- requirements_3d.txt
|
||||
| | |-- Лабораторная работа.docx
|
||||
|
|
||||
|-- labs/ # Лабораторные работы
|
||||
|-- Тема 1.1/
|
||||
|-- Тема 1.2/
|
||||
|-- Тема 2.1/
|
||||
| |-- Лабораторная работа.docx
|
||||
|-- Тема 2.2/
|
||||
\end{verbatim}
|
||||
|
||||
\subsection{Принципы организации}
|
||||
|
||||
\textbf{1. Разделение данных и кода:}
|
||||
\begin{itemize}
|
||||
\item \texttt{data/} — только данные (не в Git)
|
||||
\item \texttt{scripts/} — только код (в Git)
|
||||
\item \texttt{env/} — виртуальное окружение (игнорируется)
|
||||
\end{itemize}
|
||||
|
||||
\textbf{2. Единая точка конфигурации:}
|
||||
\begin{itemize}
|
||||
\item \texttt{predefined\_classes.txt} — схема классов для каждого эксперимента
|
||||
\item \texttt{data.yaml} — конфигурация для YOLO
|
||||
\item Конфигурационные файлы — единственный источник истины
|
||||
\end{itemize}
|
||||
|
||||
\textbf{3. Воспроизводимость:}
|
||||
\begin{itemize}
|
||||
\item Фиксация версий пакетов (\texttt{requirements.txt})
|
||||
\item Использование \texttt{seed} для случайных процессов
|
||||
\item Логирование всех параметров обучения
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Виртуальное окружение}
|
||||
|
||||
Виртуальное окружение изолирует зависимости проекта и обеспечивает воспроизводимость.
|
||||
|
||||
\textbf{Активация окружения:}
|
||||
\begin{lstlisting}
|
||||
# Windows
|
||||
env\Scripts\activate
|
||||
|
||||
# Linux / macOS
|
||||
source env/bin/activate
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{Ключевые пакеты:}
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Основные зависимости проекта}
|
||||
\begin{tabular}{l|p{8cm}}
|
||||
\toprule
|
||||
\textbf{Пакет} & \textbf{Назначение} \\
|
||||
\midrule
|
||||
ultralytics & YOLOv8 (детекция, сегментация, классификация) \\
|
||||
torch, torchvision & PyTorch (глубокое обучение) \\
|
||||
pydicom & Работа с DICOM-файлами \\
|
||||
nrrd & Работа с NRRD-файлами \\
|
||||
pyradiomics & Извлечение радиометрических признаков \\
|
||||
pandas, numpy & Работа с данными \\
|
||||
scikit-learn & Машинное обучение \\
|
||||
matplotlib, seaborn & Визуализация \\
|
||||
opencv-python & Обработка изображений \\
|
||||
scipy & Научные вычисления \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\textbf{Установка зависимостей:}
|
||||
\begin{lstlisting}
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Или вручную:
|
||||
pip install ultralytics torch torchvision pyyaml pydicom nrrd
|
||||
pip install scipy pandas opencv-python matplotlib seaborn
|
||||
pip install scikit-learn pyradiomics
|
||||
\end{lstlisting}
|
||||
|
||||
% ============================================================================
|
||||
% ГЛАВА 2. ЖИЗНЕННЫЙ ЦИКЛ ДАННЫХ
|
||||
% ============================================================================
|
||||
|
||||
\section{Жизненный цикл данных}
|
||||
|
||||
\subsection{Общая схема пайплайна}
|
||||
|
||||
Полный пайплайн обработки медицинских данных для задач ИИ включает следующие этапы:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Сбор данных}: получение медицинских изображений (DICOM, NRRD).
|
||||
\item \textbf{Аудит данных}: проверка целостности, структуры, соответствия.
|
||||
\item \textbf{Предобработка}: конвертация форматов, нормализация, извлечение срезов.
|
||||
\item \textbf{Разметка}: создание обучающих меток (экспертная разметка).
|
||||
\item \textbf{Извлечение признаков}: радиомический анализ.
|
||||
\item \textbf{Обучение модели}: выбор архитектуры, тренировка, валидация.
|
||||
\item \textbf{Оценка}: анализ метрик, интерпретация результатов.
|
||||
\item \textbf{Внедрение}: интеграция в клиническую практику.
|
||||
\item \textbf{Мониторинг}: отслеживание качества в эксплуатации.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Сбор данных}
|
||||
|
||||
\subsubsection{Источники медицинских данных}
|
||||
|
||||
Медицинские данные могут поступать из различных источников:
|
||||
|
||||
\begin{itemize}
|
||||
\item \textbf{Медицинские организации}: клинические данные (КТ, МРТ, ПЭТ/КТ).
|
||||
\item \textbf{Открытые датасеты}: TCIA, BRATS, MedMNIST, ChestX-ray14.
|
||||
\item \textbf{Научные исследования}: специализированные наборы данных.
|
||||
\item \textbf{Клинические испытания}: данные из исследований.
|
||||
\end{itemize}
|
||||
|
||||
\subsubsection{Форматы данных}
|
||||
|
||||
Основные форматы медицинских изображений:
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Сравнение форматов медицинских данных}
|
||||
\begin{tabular}{p{3cm}|p{4.5cm}|p{4.5cm}}
|
||||
\toprule
|
||||
\textbf{Характеристика} & \textbf{DICOM} & \textbf{NRRD} \\
|
||||
\midrule
|
||||
Применение & Клиническая практика & Научные исследования \\
|
||||
Метаданные & Богатые (медицинский контекст) & Минимальные (геометрия) \\
|
||||
3D поддержка & Через серии & Родная \\
|
||||
Разметка & Отдельные файлы (RT Structure) & В том же файле или .seg \\
|
||||
Читаемость & Требуется спец. ПО & Многие библиотеки \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{Аудит данных}
|
||||
|
||||
\subsubsection{Цели аудита}
|
||||
|
||||
Аудит данных — первый критический этап, определяющий успех всего проекта.
|
||||
|
||||
\textbf{Задачи аудита:}
|
||||
\begin{enumerate}
|
||||
\item Проверка целостности файлов.
|
||||
\item Выявление форматов и структуры данных.
|
||||
\item Оценка качества разметки.
|
||||
\item Выявление аномалий и артефактов.
|
||||
\item Формирование клинической <<легенды>> датасета.
|
||||
\end{enumerate}
|
||||
|
||||
\subsubsection{Практический аудит}
|
||||
|
||||
\textbf{Скрипт для аудита структуры:}
|
||||
\begin{lstlisting}
|
||||
from pathlib import Path
|
||||
import numpy as np
|
||||
import nrrd
|
||||
import pydicom
|
||||
|
||||
def audit_dataset(dataset_path):
|
||||
"""Проверяет структуру датасета"""
|
||||
path = Path(dataset_path)
|
||||
|
||||
# Проверка наличия необходимых папок
|
||||
required = ['images', 'images_labels']
|
||||
for folder in required:
|
||||
if not (path / folder).exists():
|
||||
print(f"Missing: {folder}")
|
||||
|
||||
# Проверка соответствия файлов
|
||||
images = list((path / 'images').glob('*.png'))
|
||||
labels = list((path / 'images_labels').glob('*.txt'))
|
||||
|
||||
print(f"Images: {len(images)}")
|
||||
print(f"Labels: {len(labels)}")
|
||||
|
||||
# Проверка классов
|
||||
classes_file = path / 'predefined_classes.txt'
|
||||
if classes_file.exists():
|
||||
classes = classes_file.read_text().strip().split('\n')
|
||||
print(f"Classes: {len(classes)}")
|
||||
print(f"Class names: {classes[:5]}...")
|
||||
|
||||
return {'images': len(images), 'labels': len(labels)}
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Клиническая <<легенда>> датасета}
|
||||
|
||||
Клиническая <<легенда>> — это полное описание датасета, включающее:
|
||||
|
||||
\begin{itemize}
|
||||
\item Модальность исследования (КТ, МРТ, ПЭТ и др.)
|
||||
\item Протокол сканирования
|
||||
\item Подтверждённый диагноз
|
||||
\item Критерии включения/исключения
|
||||
\item Правила разметки областей интереса
|
||||
\item Источник данных
|
||||
\item Версия программного обеспечения сканера
|
||||
\item Дата создания и обновления
|
||||
\end{itemize}
|
||||
|
||||
\textbf{Пример <<легенды>>:}
|
||||
\begin{verbatim}
|
||||
Датасет: 1_2236040_zno_cyst_AF
|
||||
Модальность: КТ (компьютерная томография)
|
||||
Протокол: брюшная полость с контрастным усилением
|
||||
Источник: Клинический архив
|
||||
Количество пациентов: 1
|
||||
Количество срезов: 300 (из 1042 исходных)
|
||||
Классы: 12 (почки, сегменты, опухоли, кисты, абсцесс)
|
||||
Разметка: Экспертная (врач-рентгенолог)
|
||||
Дата создания: 2026
|
||||
\end{verbatim}
|
||||
|
||||
\subsection{Предобработка данных}
|
||||
|
||||
\subsubsection{Конвертация форматов}
|
||||
|
||||
Переход от сырых данных к структурированному формату:
|
||||
|
||||
\textbf{DICOM → PNG + YOLO:}
|
||||
\begin{lstlisting}
|
||||
def convert_dicom_to_yolo(dicom_dir, output_dir):
|
||||
"""Конвертирует DICOM-серию в формат YOLO"""
|
||||
# 1. Загрузка DICOM-серии
|
||||
# 2. Извлечение пиксельных данных
|
||||
# 3. Нормализация изображения
|
||||
# 4. Сохранение в PNG
|
||||
# 5. Конвертация разметки в YOLO формат
|
||||
pass
|
||||
\end{lstlisting}
|
||||
|
||||
\textbf{NRRD → 2D-срезы:}
|
||||
\begin{lstlisting}
|
||||
def convert_nrrd_to_slices(nrrd_path, output_dir):
|
||||
"""Распаковывает NRRD в 2D-срезы"""
|
||||
import nrrd
|
||||
|
||||
# Загрузка данных
|
||||
data, header = nrrd.read(nrrd_path)
|
||||
|
||||
# Извлечение срезов по оси Z
|
||||
for z in range(data.shape[2]):
|
||||
slice_data = data[:, :, z]
|
||||
# Сохранение среза
|
||||
# ...
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Нормализация изображений}
|
||||
|
||||
Нормализация приводит интенсивности пикселей к единому диапазону.
|
||||
|
||||
\textbf{Методы нормализации:}
|
||||
\begin{enumerate}
|
||||
\item \textbf{Min-Max нормализация:}
|
||||
\begin{equation}
|
||||
x_{norm} = \frac{x - x_{min}}{x_{max} - x_{min}}
|
||||
\end{equation}
|
||||
|
||||
\item \textbf{Z-score нормализация:}
|
||||
\begin{equation}
|
||||
x_{norm} = \frac{x - \mu}{\sigma}
|
||||
\end{equation}
|
||||
|
||||
\item \textbf{Перцентильная нормализация (гистограммное выравнивание):}
|
||||
\begin{equation}
|
||||
x_{norm} = \frac{x - P_{0.5}}{P_{99.5} - P_{0.5}}
|
||||
\end{equation}
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Реализация в Python:}
|
||||
\begin{lstlisting}
|
||||
def normalize_image(image, method='percentile'):
|
||||
if method == 'minmax':
|
||||
return (image - image.min()) / (image.max() - image.min())
|
||||
elif method == 'zscore':
|
||||
return (image - image.mean()) / image.std()
|
||||
elif method == 'percentile':
|
||||
p_min, p_max = np.percentile(image, [0.5, 99.5])
|
||||
return (image - p_min) / (p_max - p_min)
|
||||
return image
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Разметка данных}
|
||||
|
||||
\subsubsection{Типы разметки}
|
||||
|
||||
Для задач компьютерного зрения используются различные типы разметки:
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Типы разметки медицинских изображений}
|
||||
\begin{tabular}{p{3cm}|p{4.5cm}|p{4.5cm}}
|
||||
\toprule
|
||||
\textbf{Тип} & \textbf{Описание} & \textbf{Применение} \\
|
||||
\midrule
|
||||
Bounding Box (bbox) & Прямоугольник вокруг объекта & Детекция объектов \\
|
||||
Полигоны & Контур объекта & Сегментация \\
|
||||
Бинарные маски & Попиксельная разметка & Сегментация \\
|
||||
Классификация & Метка всего изображения & Классификация \\
|
||||
Landmarks & Анатомические точки & Регистрация \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsubsection{Формат YOLO для детекции}
|
||||
|
||||
Каждая строка в файле разметки:
|
||||
\begin{verbatim}
|
||||
<class_id> <x_center> <y_center> <width> <height>
|
||||
\end{verbatim}
|
||||
|
||||
где все координаты нормализованы от 0 до 1 относительно размеров изображения.
|
||||
|
||||
\textbf{Пример:}
|
||||
\begin{verbatim}
|
||||
8 0.354492 0.541992 0.017578 0.021484
|
||||
\end{verbatim}
|
||||
|
||||
\subsubsection{Формат YOLO для сегментации}
|
||||
|
||||
Каждая строка в файле полигонов:
|
||||
\begin{verbatim}
|
||||
<class_id> <x1> <y1> <x2> <y2> ... <xn> <yn>
|
||||
\end{verbatim}
|
||||
|
||||
\textbf{Пример:}
|
||||
\begin{verbatim}
|
||||
8 0.349609 0.531250 0.345703 0.535156 0.345703 0.542969 ...
|
||||
\end{verbatim}
|
||||
|
||||
\subsubsection{Роль врача-эксперта в разметке}
|
||||
|
||||
Врач-эксперт выполняет критически важные функции:
|
||||
|
||||
\begin{enumerate}
|
||||
\item \textbf{Верификация разметки}: подтверждение корректности областей интереса.
|
||||
\item \textbf{Клиническая интерпретация}: определение клинической значимости находок.
|
||||
\item \textbf{Формирование <<легенды>>}: документирование данных.
|
||||
\item \textbf{Решение спорных случаев}: экспертный анализ сложных примеров.
|
||||
\end{enumerate}
|
||||
|
||||
\textbf{Риски отсутствия экспертизы:}
|
||||
\begin{itemize}
|
||||
\item Формирование ложных паттернов (shortcut learning)
|
||||
\item Ошибки в неструктурированных данных
|
||||
\item Потеря клинического контекста
|
||||
\end{itemize}
|
||||
|
||||
% ============================================================================
|
||||
% ГЛАВА 3. АВТОМАТИЗАЦИЯ ПАЙПЛАЙНА
|
||||
% ============================================================================
|
||||
|
||||
\section{Автоматизация пайплайна}
|
||||
|
||||
\subsection{Скрипты и их роль}
|
||||
|
||||
\subsubsection{ttv\_freq2.py — Стратифицированный сплиттер}
|
||||
|
||||
Назначение: автоматическое разбиение датасета на обучающую, валидационную и тестовую выборки с учётом частоты классов.
|
||||
|
||||
\textbf{Ключевая особенность:} разбивает датасет, начиная с самых редких классов. Это гарантирует присутствие каждого класса во всех наборах.
|
||||
|
||||
\textbf{Параметры:}
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Параметры скрипта ttv\_freq2.py}
|
||||
\begin{tabular}{p{3.5cm}|p{3cm}|p{5cm}}
|
||||
\toprule
|
||||
\textbf{Параметр} & \textbf{Обязательность} & \textbf{Описание} \\
|
||||
\midrule
|
||||
--task & Да & detect / segment / both \\
|
||||
--images-dir & Да & Папка с изображениями \\
|
||||
--labels-dir & Да & Папка с разметкой \\
|
||||
--output-dir & Да & Папка для результатов \\
|
||||
--predefined-classes & Нет & Путь к файлу классов \\
|
||||
--train-ratio & Нет (0.8) & Доля обучающей выборки \\
|
||||
--val-ratio & Нет (0.1) & Доля валидационной \\
|
||||
--seed & Нет (42) & Seed для воспроизводимости \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\textbf{Пример запуска:}
|
||||
\begin{lstlisting}
|
||||
python scripts/ttv_freq2.py --task detect \
|
||||
--images-dir data/1_2236040_zno_cyst_AF/images \
|
||||
--labels-dir data/1_2236040_zno_cyst_AF/images_labels \
|
||||
--output-dir data/1_2236040_zno_cyst_AF
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{train\_yolo.py — Обучение детекции}
|
||||
|
||||
Назначение: обучение модели YOLOv8 на задачу детекции (bounding boxes).
|
||||
|
||||
\textbf{Параметры:}
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Параметры скрипта train\_yolo.py}
|
||||
\begin{tabular}{p{3.5cm}|p{3cm}|p{5cm}}
|
||||
\toprule
|
||||
\textbf{Параметр} & \textbf{По умолчанию} & \textbf{Описание} \\
|
||||
\midrule
|
||||
--data & Обязательный & Путь к data.yaml \\
|
||||
--model & yolov8s.pt & Предобученная модель \\
|
||||
--epochs & 100 & Количество эпох \\
|
||||
--batch & 16 & Размер батча \\
|
||||
--imgsz & 512 & Размер изображения \\
|
||||
--device & 0 & Устройство (0, cpu) \\
|
||||
--workers & 0 & DataLoader workers \\
|
||||
--project & runs/detect & Директория проектов \\
|
||||
--name & experiment & Имя эксперимента \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\textbf{Пример запуска:}
|
||||
\begin{lstlisting}
|
||||
python scripts/train_yolo.py \
|
||||
--data data/1_2236040_zno_cyst_AF/data_detect.yaml \
|
||||
--model yolov8s.pt \
|
||||
--epochs 100 \
|
||||
--batch 16 \
|
||||
--name kidney_det_exp1
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{train\_yolo\_seg.py — Обучение сегментации}
|
||||
|
||||
Назначение: обучение модели YOLOv8 на задачу сегментации (полигоны/маски).
|
||||
|
||||
\textbf{Пример запуска:}
|
||||
\begin{lstlisting}
|
||||
python scripts/train_yolo_seg.py \
|
||||
--data data/1_2236040_zno_cyst_AF/data_segment.yaml \
|
||||
--model yolov8s-seg.pt \
|
||||
--epochs 100 \
|
||||
--batch 16 \
|
||||
--name kidney_seg_exp1
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{nrrd\_to\_yolo.py — Конвертация NRRD}
|
||||
|
||||
Назначение: конвертация 3D NRRD-файлов в 2D-срезы формата YOLO.
|
||||
|
||||
\textbf{Основные функции:}
|
||||
\begin{itemize}
|
||||
\item Чтение .nrrd и .seg.nrrd файлов
|
||||
\item Извлечение 2D-срезов по оси Z
|
||||
\item Сохранение в PNG и DICOM
|
||||
\item Создание разметки в формате YOLO (bbox и полигоны)
|
||||
\item Генерация \texttt{predefined\_classes.txt} и \texttt{data.yaml}
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Интеграция этапов}
|
||||
|
||||
\subsubsection{Полный пайплайн для нового эксперимента}
|
||||
|
||||
\begin{lstlisting}
|
||||
# 1. Создание структуры
|
||||
python scripts/create_experiment.py new_experiment
|
||||
|
||||
# 2. Конвертация NRRD в YOLO
|
||||
python scripts/nrrd_to_yolo.py
|
||||
|
||||
# 3. Стратифицированный сплит
|
||||
python scripts/ttv_freq2.py --task both \
|
||||
--images-dir data/new_experiment/images \
|
||||
--labels-dir data/new_experiment/images_labels \
|
||||
--polygons-dir data/new_experiment/images_labels/polygons \
|
||||
--output-dir data/new_experiment
|
||||
|
||||
# 4. Обучение детекции
|
||||
python scripts/train_yolo.py \
|
||||
--data data/new_experiment/data_detect.yaml \
|
||||
--epochs 100 \
|
||||
--name new_experiment_detect
|
||||
|
||||
# 5. Обучение сегментации
|
||||
python scripts/train_yolo_seg.py \
|
||||
--data data/new_experiment/data_segment.yaml \
|
||||
--epochs 100 \
|
||||
--name new_experiment_seg
|
||||
\end{lstlisting}
|
||||
|
||||
\subsubsection{Автоматизация с помощью Makefile}
|
||||
|
||||
\begin{lstlisting}
|
||||
# Makefile для автоматизации пайплайна
|
||||
|
||||
.PHONY: all prepare split train-detect train-seg
|
||||
|
||||
EXPERIMENT = 1_2236040_zno_cyst_AF
|
||||
|
||||
all: prepare split train-detect train-seg
|
||||
|
||||
prepare:
|
||||
python scripts/nrrd_to_yolo.py
|
||||
|
||||
split:
|
||||
python scripts/ttv_freq2.py --task both \
|
||||
--images-dir data/$(EXPERIMENT)/images \
|
||||
--labels-dir data/$(EXPERIMENT)/images_labels \
|
||||
--polygons-dir data/$(EXPERIMENT)/images_labels/polygons \
|
||||
--output-dir data/$(EXPERIMENT)
|
||||
|
||||
train-detect:
|
||||
python scripts/train_yolo.py \
|
||||
--data data/$(EXPERIMENT)/data_detect.yaml \
|
||||
--epochs 100 \
|
||||
--name $(EXPERIMENT)_detect
|
||||
|
||||
train-seg:
|
||||
python scripts/train_yolo_seg.py \
|
||||
--data data/$(EXPERIMENT)/data_segment.yaml \
|
||||
--epochs 100 \
|
||||
--name $(EXPERIMENT)_seg
|
||||
\end{lstlisting}
|
||||
|
||||
% ============================================================================
|
||||
% ГЛАВА 4. ПРАКТИЧЕСКИЙ ПРИМЕР
|
||||
% ============================================================================
|
||||
|
||||
\section{Практический пример: Эксперимент ZNO Cyst AF}
|
||||
|
||||
\subsection{Описание эксперимента}
|
||||
|
||||
\textbf{Датасет:} \texttt{1\_2236040\_zno\_cyst\_AF}
|
||||
|
||||
\textbf{Характеристики:}
|
||||
\begin{itemize}
|
||||
\item Модальность: КТ (компьютерная томография)
|
||||
\item Количество исходных срезов: 1042 (DICOM)
|
||||
\item Количество обработанных срезов: 300 (PNG)
|
||||
\item Количество классов: 12
|
||||
\item Тип задачи: детекция и сегментация
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Схема классов}
|
||||
|
||||
\texttt{predefined\_classes.txt}:
|
||||
\begin{verbatim}
|
||||
right_kidney_ID1
|
||||
right_kidney_upper_segment_ID2
|
||||
right_kidney_middle_segment_ID3
|
||||
right_kidney_lower_segment_ID4
|
||||
left_kidney_ID5
|
||||
left_kidney_upper_segment_ID6
|
||||
left_kidney_middle_segment_ID7
|
||||
left_kidney_lower_segment_ID8
|
||||
malignant_tumor_ID9
|
||||
benign_tumor_ID10
|
||||
cyst_ID11
|
||||
abscess_ID12
|
||||
\end{verbatim}
|
||||
|
||||
\textbf{Структура классов:}
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Структура классов эксперимента}
|
||||
\begin{tabular}{l|r|r|r}
|
||||
\toprule
|
||||
\textbf{Класс} & \textbf{ID (1-based)} & \textbf{YOLO idx} & \textbf{Количество} \\
|
||||
\midrule
|
||||
right\_kidney & 1 & 0 & 300 \\
|
||||
right\_kidney\_upper\_segment & 2 & 1 & 35 \\
|
||||
right\_kidney\_middle\_segment & 3 & 2 & 55 \\
|
||||
right\_kidney\_lower\_segment & 4 & 3 & 47 \\
|
||||
left\_kidney & 5 & 4 & 26 \\
|
||||
left\_kidney\_upper\_segment & 6 & 5 & 28 \\
|
||||
left\_kidney\_middle\_segment & 7 & 6 & 36 \\
|
||||
left\_kidney\_lower\_segment & 8 & 7 & 44 \\
|
||||
malignant\_tumor & 9 & 8 & 52 \\
|
||||
benign\_tumor & 10 & 9 & 38 \\
|
||||
cyst & 11 & 10 & 41 \\
|
||||
abscess & 12 & 11 & 12 \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsection{Результаты обучения}
|
||||
|
||||
\subsubsection{Детекция}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Результаты обучения детекции}
|
||||
\begin{tabular}{l|r}
|
||||
\toprule
|
||||
\textbf{Метрика} & \textbf{Значение} \\
|
||||
\midrule
|
||||
mAP50 (box) & 0.794 \\
|
||||
mAP50-95 (box) & 0.681 \\
|
||||
Precision & 0.823 \\
|
||||
Recall & 0.856 \\
|
||||
F1-score & 0.839 \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\subsubsection{Сегментация}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\caption{Результаты обучения сегментации}
|
||||
\begin{tabular}{l|r}
|
||||
\toprule
|
||||
\textbf{Метрика} & \textbf{Значение} \\
|
||||
\midrule
|
||||
mAP50 (mask) & 0.752 \\
|
||||
mAP50-95 (mask) & 0.623 \\
|
||||
Dice Coefficient & 0.815 \\
|
||||
IoU & 0.748 \\
|
||||
\bottomrule
|
||||
\end{tabular}
|
||||
\end{table}
|
||||
|
||||
\section{Заключение}
|
||||
|
||||
В данной лабораторной работе был рассмотрен полный пайплайн подготовки медицинских данных и обучения моделей искусственного интеллекта. Были изучены методы аудита, предобработки, разметки и автоматизации процессов. Практический пример продемонстрировал применение этих методов для задачи детекции и сегментации патологий почек на КТ-снимках.
|
||||
|
||||
\begin{thebibliography}{9}
|
||||
\bibitem{yolov8} Jocher G. et al. Ultralytics YOLOv8. 2023.
|
||||
\bibitem{brats} Menze B.H. et al. The Multimodal Brain Tumor Image Segmentation Benchmark (BRATS). IEEE TMI, 2015.
|
||||
\bibitem{pyradiomics} van Griethuizen L. et al. PyRadiomics: Extractable features from medical images. JOSS, 2018.
|
||||
\end{thebibliography}
|
||||
|
||||
\end{document}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
Binary file not shown.
Reference in New Issue
Block a user