Files
ai-med-edu/README.md
T

467 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 классов)
```txt
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:**
```bash
cd D:\ai-med-edu
env\Scripts\activate
```
**Linux / macOS:**
```bash
cd /path/to/ai-med-edu
source env/bin/activate
```
### 2. Проверка GPU
```bash
python scripts/check_PyTorch_gpu.py
```
Ожидаемый результат:
```
CUDA доступна!
Количество доступных GPU: 1
GPU 0: NVIDIA GeForce RTX 3060
```
### 3. Установка зависимостей (при необходимости)
```bash
pip install ultralytics torch torchvision pyyaml pydicom nrrd scipy pandas opencv-python
```
## 📋 Полный пайплайн обучения
### Вариант A: Детекция (bounding boxes)
```bash
# Шаг 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: Сегментация (полигоны)
```bash
# Шаг 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: Обе задачи сразу (общий сплит)
```bash
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 с сохранением структуры папок.
**Использование:**
```bash
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-кода:
```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. Создание структуры вручную
```bash
mkdir -p data/new_experiment/{images,images_labels/polygons,images_result}
```
Или используйте шаблон из папки `data/example/`.
### 2. Создание схемы классов
```bash
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. Запуск обучения
```bash
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 классов (почки, сегменты, опухоли, кисты, абсцесс)
## 📄 Лицензия
Образовательный проект. Медицинские данные используются в исследовательских и учебных целях.