Initial commit: project structure, scripts and documentation

This commit is contained in:
2026-08-22 13:17:29 +03:00
commit 5042305df0
54 changed files with 14166 additions and 0 deletions
+467
View File
@@ -0,0 +1,467 @@
# 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 классов (почки, сегменты, опухоли, кисты, абсцесс)
## 📄 Лицензия
Образовательный проект. Медицинские данные используются в исследовательских и учебных целях.