330 lines
13 KiB
Markdown
330 lines
13 KiB
Markdown
# 🦴 DXA Quality Assessment
|
||
|
||
[](https://www.python.org/)
|
||
[](https://fastapi.tiangolo.com/)
|
||
[](https://pytorch.org/)
|
||
|
||
## Описание
|
||
|
||
Сервис для автоматизированной оценки качества денситометрических исследований (DXA). Система анализирует DICOM-изображения костной денситометрии и определяет качество исследования по следующим критериям:
|
||
|
||
- **Артефакты** — движение, размытость, металлические объекты, имплантаты
|
||
- **Позиционирование** — правильное расположение анатомической области в кадре
|
||
- **Полнота изображения** — видимость всех анатомических структур (позвонки L1-L4, бедро)
|
||
- **Ротация** — корректный угол поворота (для исследования бедра)
|
||
- **ROI-валидация** — правильность расположения области интереса
|
||
|
||
### Основные возможности
|
||
|
||
- 🔬 **Анализ DICOM** — загрузка и обработка медицинских изображений
|
||
- 🧠 **Классификация** — бинарная оценка качества (OK / Violation)
|
||
- 🔍 **Детекция нарушений** — определение типа нарушения:
|
||
- `correct` — качество соответствует норме
|
||
- `artifact_motion` — артефакт движения
|
||
- `artifact_other` — прочие артефакты
|
||
- `position_error` — ошибка позиционирования
|
||
- `rotation` — нарушение ротации
|
||
- `incomplete_view` — неполный вид
|
||
- `roi_error` — ошибка ROI
|
||
- `labeling_error` — ошибка разметки
|
||
- 🌐 **REST API** — интеграция с внешними системами
|
||
- 📊 **Веб-интерфейс** — загрузка и визуализация результатов
|
||
- 📈 **Экспорт** — выгрузка результатов в XLSX
|
||
|
||
---
|
||
|
||
## Архитектура
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ FastAPI Server │
|
||
│ (port 8000) │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ /api/v1/analyze → Basic quality prediction │
|
||
│ /api/v1/analyze/detailed → Full report with metrics │
|
||
│ /api/v1/analyze/sr → DICOM SR (Structured Report) │
|
||
│ /api/v1/batch → Batch processing │
|
||
│ /api/v1/export → XLSX export │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ ┌──────────────┐ ┌─────────────────┐ │
|
||
│ │ ResNet18 │───▶│ Quality Model │ │
|
||
│ │ (pretrained) │ │ (binary class) │ │
|
||
│ └──────────────┘ └────────┬────────┘ │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ ┌─────────────────────┐ │
|
||
│ │ Detailed Assessment │ │
|
||
│ │ - Motion detection │ │
|
||
│ │ - Artifact detection│ │
|
||
│ │ - ROI validation │ │
|
||
│ │ - View completeness│ │
|
||
│ └─────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Быстрый старт
|
||
|
||
### Требования
|
||
|
||
- Python 3.10+
|
||
- PyTorch 2.0+
|
||
- 4GB+ RAM
|
||
- (опционально) GPU CUDA/MPS для ускорения
|
||
|
||
### Установка
|
||
|
||
```bash
|
||
# Клонирование
|
||
git clone https://github.com/yourusername/bone-quality-assessment.git
|
||
cd bone-quality-assessment
|
||
|
||
# Создание виртуального окружения
|
||
python -m venv venv
|
||
source venv/bin/activate # Linux/Mac
|
||
# venv\Scripts\activate # Windows
|
||
|
||
# Установка зависимостей
|
||
pip install -r requirements.txt
|
||
|
||
# Загрузка модели (опционально)
|
||
# Поместите файл модели в models/dxa_model.pth
|
||
```
|
||
|
||
### Запуск сервера
|
||
|
||
```bash
|
||
# Локальный запуск
|
||
python -m uvicorn src.main:app --host 0.0.0.0 --port 8000
|
||
|
||
# Или через run.py
|
||
python run.py
|
||
```
|
||
|
||
После запуска:
|
||
- Web-интерфейс: http://localhost:8000
|
||
- Swagger UI: http://localhost:8000/docs
|
||
- ReDoc: http://localhost:8000/redoc
|
||
|
||
### Docker
|
||
|
||
```bash
|
||
# Сборка
|
||
docker build -t dxa-quality-api .
|
||
|
||
# Запуск
|
||
docker run -p 8000:8000 dxa-quality-api
|
||
```
|
||
|
||
---
|
||
|
||
## API Endpoints
|
||
|
||
| Метод | Эндпоинт | Описание |
|
||
|-------|----------|----------|
|
||
| GET | `/` | Главная страница (веб-интерфейс) |
|
||
| GET | `/api/v1/health` | Проверка статуса сервиса |
|
||
| POST | `/api/v1/analyze` | Базовый анализ изображения |
|
||
| POST | `/api/v1/analyze/detailed` | Детальный анализ с метриками |
|
||
| POST | `/api/v1/analyze/sr` | DICOM SR отчёт |
|
||
| POST | `/api/v1/batch` | Пакетный анализ |
|
||
| POST | `/api/v1/export` | Анализ и экспорт в XLSX |
|
||
|
||
### Пример использования
|
||
|
||
```bash
|
||
# Анализ файла
|
||
curl -X POST "http://localhost:8000/api/v1/analyze" \
|
||
-H "accept: application/json" \
|
||
-H "Content-Type: multipart/form-data" \
|
||
-F "file=@/path/to/image.dcm"
|
||
|
||
# Детальный анализ
|
||
curl -X POST "http://localhost:8000/api/v1/analyze/detailed" \
|
||
-H "accept: application/json" \
|
||
-H "Content-Type: multipart/form-data" \
|
||
-F "file=@/path/to/image.dcm"
|
||
```
|
||
|
||
### Ответ детального анализа
|
||
|
||
```json
|
||
{
|
||
"anatomical_region": "spine",
|
||
"quality_class": 1,
|
||
"quality_label": "Violation detected",
|
||
"violation_type": "artifact_motion",
|
||
"reason": "Обнаружен артефакт движения (размытие)",
|
||
"confidence": 0.85,
|
||
"confidence_per_class": {
|
||
"correct": 0.15,
|
||
"violation": 0.85
|
||
},
|
||
"view_quality": "full",
|
||
"metrics": {
|
||
"motion": {
|
||
"motion_detected": true,
|
||
"blur_laplacian": 0.0008,
|
||
"severity": "HIGH"
|
||
},
|
||
"artifacts": {
|
||
"any_detected": false,
|
||
"metal_detected": false
|
||
},
|
||
"roi_check": {
|
||
"valid": true
|
||
}
|
||
},
|
||
"overall_quality": "POOR",
|
||
"severity": "HIGH"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Структура проекта
|
||
|
||
```
|
||
bone_2026/
|
||
├── src/
|
||
│ ├── main.py # FastAPI приложение
|
||
│ ├── run.py # Запуск сервера
|
||
│ ├── dxa/ # DXA модуль
|
||
│ │ ├── model.py # ResNet18 классификатор
|
||
│ │ ├── dataset.py # Загрузчик данных
|
||
│ │ ├── train.py # Обучение модели
|
||
│ │ └── inference.py # Инференс и batch-обработка
|
||
│ ├── quality/ # Оценка качества
|
||
│ │ ├── quality_scorer.py # Базовый скорer
|
||
│ │ └── detailed_assessment.py # Детальный анализ
|
||
│ ├── api/ # REST API
|
||
│ │ ├── endpoints.py # Дополнительные эндпоинты
|
||
│ │ └── static/ # Веб-интерфейс
|
||
│ └── utils/ # Утилиты
|
||
├── models/ # Обученные модели
|
||
│ └── dxa_model.pth # Модель классификатора
|
||
├── dataset_hack/ # Датасет для обучения/тестирования
|
||
├── docs/ # Документация
|
||
├── Dockerfile
|
||
├── requirements.txt
|
||
└── README.md
|
||
```
|
||
|
||
---
|
||
|
||
## Обучение модели
|
||
|
||
### Подготовка данных
|
||
|
||
1. Разместите DICOM-файлы в `dataset_hack/НД_для_обучения/Исследования/`
|
||
2. Подготовьте Excel-файл разметки `dataset_hack/НД_для_обучения/разметка.xlsx`
|
||
|
||
Столбцы разметки:
|
||
- `study_uid` — ID исследования
|
||
- `позвоночник_укладка`, `позвоночник_ось`, `позвоночник_артефакты` — критерии для позвоночника
|
||
- `бедро_позиция_лев`, `бедро_roi_лев` — критерии для левого бедра
|
||
- `бедро_позиция_прав`, `бедро_roi_прав` — критерии для правого бедра
|
||
- `итог_позвоночник`, `итог_бедро_лев`, `итог_бедро_прав` — итоговая оценка (0/1)
|
||
|
||
### Запуск обучения
|
||
|
||
```bash
|
||
python src/dxa/train.py \
|
||
--epochs 20 \
|
||
--batch-size 8 \
|
||
--backbone resnet18 \
|
||
--output-dir models
|
||
```
|
||
|
||
### Аргументы
|
||
|
||
| Параметр | По умолчанию | Описание |
|
||
|----------|-------------|----------|
|
||
| `--data-root` | `dataset_hack` | Путь к директории с данными |
|
||
| `--annotation-path` | `dataset_hack/НД_для_обучения/разметка.xlsx` | Путь к файлу разметки |
|
||
| `--epochs` | 20 | Количество эпох |
|
||
| `--batch-size` | 8 | Размер батча |
|
||
| `--backbone` | `resnet18` | Архитектура (resnet18/resnet34/efficientnet_b0) |
|
||
| `--input-size` | 224 | Размер входного изображения |
|
||
| `--output-dir` | `models` | Директория для сохранения модели |
|
||
|
||
---
|
||
|
||
## Инференс
|
||
|
||
### Одиночный файл
|
||
|
||
```bash
|
||
python src/dxa/inference.py \
|
||
--input-path path/to/image.dcm \
|
||
--output-path result.xlsx
|
||
```
|
||
|
||
### Директория
|
||
|
||
```bash
|
||
python src/dxa/inference.py \
|
||
--input-path dataset_hack/Для\ теста \
|
||
--output-path results.xlsx \
|
||
--model-path models/dxa_model.pth
|
||
```
|
||
|
||
### Выходной формат (XLSX/CSV)
|
||
|
||
| Колонка | Описание |
|
||
|---------|----------|
|
||
| `path_to_study` | Путь к директории исследования |
|
||
| `study_uid` | StudyInstanceUID |
|
||
| `image_uid` | SOPInstanceUID |
|
||
| `anatomical_region` | Анатомическая область (spine/hip_left/hip_right) |
|
||
| `quality_class` | Класс качества (0 — OK, 1 — Violation) |
|
||
| `violation_type` | Тип нарушения |
|
||
| `processing_status` | Статус обработки |
|
||
| `time_of_processing` | Время обработки (сек) |
|
||
|
||
---
|
||
|
||
## Метрики качества
|
||
|
||
### Детекция движения
|
||
|
||
- **Laplacian variance** — дисперсия лапласиана (меньше = сильнее размытие)
|
||
- **FFT high-frequency ratio** — отношение высокочастотной энергии (меньше = размытие)
|
||
- **Edge duplication** — проверка "призрачных" контуров
|
||
|
||
### Детекция артефактов
|
||
|
||
- **Metal detection** — яркие области (>99.5 перцентиль)
|
||
- **Implant detection** — линейные структуры (морфологические операции)
|
||
- **Cement detection** — локальные яркие пятна в ROI
|
||
- **Calcification** — малые яркие области вне ROI
|
||
|
||
### Полнота изображения
|
||
|
||
- **Spine**: подсчет позвонков (ожидается 3-4), проверка межпозвоночных промежутков
|
||
- **Hip**: проверка видимости шейки бедра, большого/малого вертелов
|
||
|
||
### Валидация ROI
|
||
|
||
- Проверка отступа от краев (>10 пикселей)
|
||
- Проверка размера ROI (>30% высоты, >20% ширины изображения)
|
||
|
||
---
|
||
|
||
## Лицензия
|
||
|
||
MIT License
|
||
|
||
## Команда
|
||
|
||
- **Грачев Денис** — Разработка
|
||
- **Грачев Татьяна** — Капитан
|
||
|
||
---
|
||
|
||
<div align="center">
|
||
<sub>Built for Bone Quality Assessment Hackathon 2026</sub>
|
||
</div>
|