Initial commit: project structure, scripts and documentation
This commit is contained in:
@@ -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 классов (почки, сегменты, опухоли, кисты, абсцесс)
|
||||
|
||||
## 📄 Лицензия
|
||||
|
||||
Образовательный проект. Медицинские данные используются в исследовательских и учебных целях.
|
||||
Reference in New Issue
Block a user