Files
ai-med-edu/README.md
T

22 KiB
Raw Blame History

AI Medical Education & Imaging (ai-med-edu)

Образовательный проект по AI-обработке медицинских изображений: детекция и сегментация анатомических структур (почки, их сегменты, опухоли, кисты, абсцессы) на основе DICOM и 3D NRRD данных с использованием архитектур YOLO.

🎯 Цели проекта

  • Конвертация медицинских 3D-данных (NRRD, DICOM) в 2D-срезы формата YOLO
  • Обучение моделей детекции (yolov8s, yolo26n) и сегментации (yolov8s-seg)
  • Автоматическая подготовка и стратифицированное разделение датасета на train/val/test
  • Поддержка индивидуальных схем классов для каждого препарата
  • Проверка доступности GPU (PyTorch + CUDA)
  • Образовательные материалы: лекции, семинары, лабораторные работы

📂 Структура репозитория

ai-med-edu/
│
├── README.md                             # Этот файл
├── ai-use-program.doc                    # Учебная программа
├── references.txt                        # Список литературы
├── labels.cache                          # Кэш лейблов YOLO
│
├── data/                                 # Эксперименты (каждый препарат - отдельная папка)
│   ├── 1_2236040_zno_cyst_AF/            # Эксперимент 1: ZNO Cyst AF
│   │   ├── predefined_classes.txt        # Схема классов (12 классов)
│   │   ├── data.yaml                     # Конфиг YOLO
│   │   ├── 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
│   │
│   ├── example/                          # Пример структуры
│   │   ├── README.md
│   │   ├── images/
│   │   ├── images_labels/
│   │   │   └── polygons/
│   │   └── images_results/
│   │
│   └── prep/                             # Подготовительные данные
│       ├── predefined_classes.txt
│       ├── csv/                          # CSV-файлы с разметкой
│       ├── images/                       # DCM и JPG файлы
│       ├── images_labels/                # TXT-лейблы
│       │   └── polygons/
│       └── images_results/               # Результаты
│           └── masks_sam/
│
├── 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/                         # Скрипты по теме 2.1
│   │   ├── analysis.py
│   │   ├── config_3d.py
│   │   ├── feature_3d.py
│   │   └── segmentation.py
│   └── Тема 2.2/                         # Скрипты по теме 2.2
│       └── nrrd_to_yolo.py               # Конвертация NRRD → YOLO
│
├── env/                                  # Виртуальное окружение Python
│   ├── Include/
│   ├── Lib/
│   │   └── site-packages/                # Установленные пакеты
│   ├── Scripts/                          # Исполняемые файлы
│   ├── etc/
│   ├── share/
│   └── pyvenv.cfg
│
├── lectures/                             # Лекционные материалы
│   ├── К26_1_1.pdf
│   ├── К26_2_1.pdf
│   └── К26_2_2.pdf
│
├── seminars/                             # Семинарские занятия
│   ├── FeatureExtractionClient.ipynb
│   ├── Тема 1.1/                         # Jupyter ноутбуки
│   │   ├── 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
│   └── Тема 2.2/
│
└── labs/                                 # Лабораторные работы
    ├── Тема 1.1/
    ├── Тема 1.2/
    ├── Тема 2.1/
    │   └── Лабораторная работа.docx
    └── Тема 2.2/

🏷️ Схема классов (predefined_classes.txt)

Каждый эксперимент имеет СВОЙ СОБСТВЕННЫЙ файл predefined_classes.txt, расположенный в папке эксперимента. Это позволяет использовать разные наборы классов для разных препаратов.

Формат: один класс на строку, позиция в файле = YOLO index (0-based).

Пример: data/1_2236040_zno_cyst_AF/predefined_classes.txt (12 классов)

right_kidney                      # ID 1  →  YOLO idx 0
right_kidney_upper_segment        # ID 2  →  YOLO idx 1
right_kidney_middle_segment       # ID 3  →  YOLO idx 2
right_kidney_lower_segment        # ID 4  →  YOLO idx 3
left_kidney                       # ID 5  →  YOLO idx 4
left_kidney_upper_segment         # ID 6  →  YOLO idx 5
left_kidney_middle_segment        # ID 7  →  YOLO idx 6
left_kidney_lower_segment         # ID 8  →  YOLO idx 7
malignant_tumor                   # ID 9  →  YOLO idx 8
benign_tumor                      # ID 10 →  YOLO idx 9
cyst                              # ID 11 →  YOLO idx 10
abscess                           # ID 12 →  YOLO idx 11

Важно: Исходные лейблы (Label Studio / CVAT) используют 1-based ID (1–N). Скрипт ttv_freq2.py автоматически перенумеровывает их в 0-based формат при копировании в папку labels/. Это необходимо, так как YOLOv8 требует, чтобы все ID в .txt-файлах были в диапазоне [0, nc-1] без пропусков.

🚀 Быстрый старт

1. Активация окружения

Windows:

cd D:\ai-med-edu
env\Scripts\activate

Linux / macOS:

cd /path/to/ai-med-edu
source env/bin/activate

2. Проверка GPU

python scripts/check_PyTorch_gpu.py

Ожидаемый результат:

CUDA доступна!
Количество доступных GPU: 1
GPU 0: NVIDIA GeForce RTX 3060

3. Установка зависимостей (при необходимости)

pip install ultralytics torch torchvision pyyaml pydicom nrrd scipy pandas opencv-python

📋 Полный пайплайн обучения

Вариант A: Детекция (bounding boxes)

# Шаг 1: Создать сплит с перенумерацией классов
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

# Шаг 2: Запустить обучение
python scripts/train_yolo.py ^
    --data data/1_2236040_zno_cyst_AF/data.yaml ^
    --model yolov8s.pt ^
    --epochs 100 ^
    --batch 16 ^
    --name kidney_det_exp1

Вариант B: Сегментация (полигоны)

# Шаг 1: Создать сплит для сегментации
python scripts/ttv_freq2.py --task segment ^
    --images-dir data/1_2236040_zno_cyst_AF/images ^
    --labels-dir data/1_2236040_zno_cyst_AF/images_labels/polygons ^
    --output-dir data/1_2236040_zno_cyst_AF

# Шаг 2: Запустить обучение
python scripts/train_yolo_seg.py ^
    --data data/1_2236040_zno_cyst_AF/data.yaml ^
    --model yolov8s-seg.pt ^
    --epochs 100 ^
    --batch 16 ^
    --name kidney_seg_exp1

Вариант C: Обе задачи сразу (общий сплит)

python scripts/ttv_freq2.py --task both ^
    --images-dir data/1_2236040_zno_cyst_AF/images ^
    --labels-dir data/1_2236040_zno_cyst_AF/images_labels ^
    --polygons-dir data/1_2236040_zno_cyst_AF/images_labels/polygons ^
    --output-dir data/1_2236040_zno_cyst_AF

📜 Описание скриптов

scripts/ttv_freq2.py — Стратифицированный сплиттер

Ключевая особенность: разбивает датасет, начиная с самых редких классов. Это гарантирует присутствие каждого класса в train/val/test наборах, что критично для медицинских данных с несбалансированными классами.

Возможности:

  • Автоматический поиск predefined_classes.txt в папке эксперимента
  • Автоматическая перенумерация 1-based → 0-based для YOLOv8
  • Поддержка детекции, сегментации или обеих задач одновременно
  • Стратифицированное разбиение по частоте классов
  • Автоматическая генерация data.yaml с абсолютными путями
  • Создание изолированной папки labels/ (полное копирование)
  • Автоматическая очистка старых .cache файлов

Параметры:

Параметр Описание По умолчанию
--task detect / segment / both обязательный
--images-dir Папка с изображениями обязательный
--labels-dir Папка с bbox или полигонами обязательный
--polygons-dir Папка с полигонами (both) -
--output-dir Папка для результатов обязательный
--predefined-classes Путь к файлу классов <output-dir>/predefined_classes.txt
--train-ratio Доля обучающей выборки 0.8
--val-ratio Доля валидационной выборки 0.1
--seed Seed для воспроизводимости 42

scripts/train_yolo.py — Обучение детекции (bounding boxes)

Параметры:

Параметр Описание По умолчанию
--data Путь к data.yaml обязательный
--model Предобученная модель yolov8s.pt
--epochs Количество эпох 100
--batch Batch size 16
--imgsz Размер изображения 512
--device Устройство (0, cpu) 0
--workers DataLoader workers 0
--project Директория проектов runs/detect
--name Имя эксперимента experiment

scripts/train_yolo_seg.py — Обучение сегментации (полигоны/маски)

Параметры (аналогичны train_yolo.py, но со спецификой сегментации):

Параметр Описание По умолчанию
--data Путь к data.yaml обязательный
--model Предобученная модель yolov8s-seg.pt
--epochs Количество эпох 100
--batch Batch size 16
--imgsz Размер изображения 512
--device Устройство (0, cpu) 0
--workers DataLoader workers 0
--project Директория проектов runs/segment
--name Имя эксперимента seg_experiment

scripts/nrrd_to_yolo.py — Конвертация NRRD → YOLO (Тема 2.2)

Конвертирует 3D NRRD файлы в 2D срезы формата YOLO с сохранением структуры папок.

Использование:

python scripts/Тема\ 2.2/nrrd_to_yolo.py

Скрипты темы 2.1 (scripts/Тема 2.1/)

  • analysis.py — Анализ данных и визуализация
  • config_3d.py — Конфигурация для 3D обработки
  • feature_3d.py — Извлечение признаков из 3D данных
  • segmentation.py — Сегментация 3D данных

📁 Структура результатов обучения

После обучения YOLOv8 генерирует отчёты в: runs/{detect|segment}/{name}/

runs/segment/kidney_seg_exp1/
│
├── weights/
│   ├── best.pt                  # Лучшая модель (для инференса)
│   └── last.pt                  # Модель после последней эпохи
│
├── results.png                  # Графики loss и метрик по эпохам
├── confusion_matrix.png         # Матрица ошибок
├── confusion_matrix_normalized.png
├── F1_curve.png                 # F1-score по confidence
├── PR_curve.png                 # Precision-Recall кривая
├── P_curve.png                  # Precision по confidence
├── R_curve.png                  # Recall по confidence
├── results.csv                  # Числовые метрики по эпохам
└── args.yaml                    # Сохранённые параметры обучения

🔮 Инференс (применение обученной модели)

Пример Python-кода:

from ultralytics import YOLO

# Загрузка обученной модели
model = YOLO('runs/segment/kidney_seg_exp1/weights/best.pt')

# Предсказание на новых изображениях
results = model.predict(
    source='data/1_2236040_zno_cyst_AF/images/slice_0573.png',
    conf=0.25,              # Порог уверенности
    iou=0.45,               # Порог IoU для NMS
    save=True,              # Сохранить результат
    project='predictions',
    name='inference_test'
)

# Анализ результатов
for r in results:
    print(f"Обнаружено объектов: {len(r.boxes)}")
    for box in r.boxes:
        cls_id = int(box.cls[0])
        cls_name = model.names[cls_id]
        conf = float(box.conf[0])
        print(f"  - {cls_name}: {conf:.2f}")

🆕 Создание нового эксперимента

1. Создание структуры вручную

mkdir -p data/new_experiment/{images,images_labels/polygons,images_result}

Или используйте шаблон из папки data/example/.

2. Создание схемы классов

notepad data\new_experiment\predefined_classes.txt

Запишите классы (по одному на строку):

organ
tissue_type_1
tissue_type_2
lesion

3. Помещение данных

Скопируйте изображения в:

  • data/new_experiment/images/

Скопируйте разметку в:

  • data/new_experiment/images_labels/ (для детекции)
  • data/new_experiment/images_labels/polygons/ (для сегментации)

4. Запуск обучения

python scripts/ttv_freq2.py --task segment ^
    --images-dir data/new_experiment/images ^
    --labels-dir data/new_experiment/images_labels/polygons ^
    --output-dir data/new_experiment

python scripts/train_yolo_seg.py ^
    --data data/new_experiment/data.yaml ^
    --epochs 100 ^
    --name new_experiment_seg

⚠️ Особенности Windows

  1. Многопоточность DataLoader: Используйте --workers 0 при ошибках доступа к файлам. На Linux/macOS можно ставить --workers 8 для ускорения.

  2. Пути: В data.yaml и .txt-файлах используются абсолютные пути с прямыми слэшами (/) для совместимости с YOLOv8.

  3. Кодировка: Все файлы обрабатываются в UTF-8, кириллица в именах классов поддерживается.

  4. Пути с пробелами: Имена файлов с пробелами могут вызывать проблемы. Рекомендуется переименовывать файлы, убирая пробелы.

📚 Образовательные материалы

Лекции (lectures/)

  • К26_1_1.pdf — Введение в обработку медицинских изображений
  • К26_2_1.pdf — Архитектуры нейронных сетей для медицинской визуализации
  • К26_2_2.pdf — Применение YOLO в медицинской диагностике

Семинары (seminars/)

  • Тема 1.1/ — Работа с датасетами, шумоподавление, сегментация
  • Тема 1.2/ — Практикум по обучению моделей
  • Тема 2.1/ — Радиомика и 3D-сегментация
  • Тема 2.2/ — Конвертация NRRD в YOLO формат

Лабораторные работы (labs/)

  • Пошаговые инструкции по темам курса
  • Включают теоретический материал и практические задания

🛠️ Известные проблемы и решения

Проблема: "Label class X exceeds dataset class count N"

Решение: Скрипт ttv_freq2.py автоматически перенумеровывает классы из 1-based (Label Studio) в 0-based (YOLOv8).

Проблема: "Image Not Found" ошибки

Решение: Использовать --workers 0, проверить наличие изображений, пересоздать сплит. Убедиться, что пути в data.yaml корректны.

Проблема: Редкие классы показывают Recall=0

Решение: Увеличить число эпох (100-300), использовать imgsz=640, стратифицированный сплит гарантирует минимум 1 пример в train для каждого класса.

Проблема: Не удаётся прочитать NRRD файлы

Решение: Убедитесь, что установлены зависимости: pip install nrrd pydicom scipy

Проблема: Ошибки с путями в Windows (пробелы в именах)

Решение: Переименуйте файлы, убрав пробелы. Например: "501 arterial ax 1mm iDose (5).nrrd" → "501_arterial_ax_1mm_iDose_5.nrrd"

📝 Changelog

2026-08-19 (текущая версия)

  • ✅ Поддержка двух экспериментов: 1_2236040_zno_cyst_AF и prep
  • ✅ Реальная структура данных: DICOM (1042 среза), PNG (300 срезов)
  • ✅ Разметка в формате YOLO для 300 изображений
  • ✅ Образовательные материалы: лекции (3 PDF), семинары (Jupyter ноутбуки)
  • ✅ Скрипты для работы с 3D данными (Тема 2.1 и 2.2)
  • ✅ Виртуальное окружение с полным набором зависимостей
  • ✅ predefined_classes.txt для каждого эксперимента
  • ✅ Стратифицированный сплиттер ttv_freq2.py
  • ✅ Скрипты обучения детекции и сегментации

Структура данных

  • DICOM файлы: 1042 среза (slice_0000.dcm — slice_1041.dcm)
  • PNG изображения: 300 срезов (slice_0573.png — slice_0872.png)
  • Разметка: 300 файлов .txt в формате YOLO
  • Классы: 12 классов (почки, сегменты, опухоли, кисты, абсцесс)

📄 Лицензия

Образовательный проект. Медицинские данные используются в исследовательских и учебных целях.