From b67245270d0dc99879b7f52eaa5d877c8bb1260f Mon Sep 17 00:00:00 2001 From: denis Date: Wed, 23 Sep 2026 00:37:02 +0300 Subject: [PATCH] develop - hack_2026 --- docs/architecture-analytical.html | 446 ++++++++++++++++++ docs/architecture-analytical.md | 652 +++++++++++++++++++++++++++ docs/architecture-analytical.png | Bin 0 -> 24267 bytes docs/architecture-analytical_001.png | Bin 0 -> 25723 bytes docs/architecture-analytical_002.png | Bin 0 -> 16063 bytes docs/architecture-analytical_003.png | Bin 0 -> 19986 bytes docs/architecture-analytical_004.png | Bin 0 -> 18558 bytes docs/architecture-analytical_005.png | Bin 0 -> 15001 bytes docs/architecture-analytical_006.png | Bin 0 -> 18003 bytes requirements.txt | 109 +++-- src/api/static/index.html | 127 +++++- src/api/static/js/dxa-app.js | 285 ++++++++++-- src/training/train_model.py | 2 +- 13 files changed, 1513 insertions(+), 108 deletions(-) create mode 100644 docs/architecture-analytical.html create mode 100644 docs/architecture-analytical.md create mode 100644 docs/architecture-analytical.png create mode 100644 docs/architecture-analytical_001.png create mode 100644 docs/architecture-analytical_002.png create mode 100644 docs/architecture-analytical_003.png create mode 100644 docs/architecture-analytical_004.png create mode 100644 docs/architecture-analytical_005.png create mode 100644 docs/architecture-analytical_006.png diff --git a/docs/architecture-analytical.html b/docs/architecture-analytical.html new file mode 100644 index 0000000..fd85ff3 --- /dev/null +++ b/docs/architecture-analytical.html @@ -0,0 +1,446 @@ + + architecture-analytical + + + + + + + + + + + + + + + + +
+ +

Аналитический документ: DXA Quality Assessment System

+

Содержание

+
    +
  1. Обзор системы
  2. +
  3. Архитектура
  4. +
  5. Компоненты системы
  6. +
  7. Пайплайн обработки
  8. +
  9. API Endpoints
  10. +
  11. Модели и алгоритмы
  12. +
  13. PlantUML Диаграммы
  14. +
+
+

Обзор системы

+

Система DXA Quality Assessment — это медицинский AI-сервис для автоматизированной оценки качества исследований DXA (денситометрия костей). Система анализирует DICOM файлы и определяет:

+ +

Целевое назначение

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ПараметрЗначение
ТипМедицинский AI сервис
Входные данныеDICOM файлы (DXA исследования)
Выходные данныеJSON / XLSX отчеты
Тип классификацииБинарный (OK / Violation)
Целевые регионыПозвоночник (L1-L4), Бедро (левое/правое)
+
+

Архитектура

+

Высокоуровневая архитектура

+
┌─────────────────────────────────────────────────────────────────────────┐
+│                          DXA Quality Assessment                          │
+├─────────────────────────────────────────────────────────────────────────┤
+│                                                                          │
+│  ┌──────────────┐    ┌──────────────┐    ┌──────────────────────────┐ │
+│  │   Клиент     │───▶│   FastAPI    │───▶│   Orchestrator           │ │
+│  │  (Web UI)    │    │   Server     │    │   (Pipeline Control)    │ │
+│  └──────────────┘    └──────────────┘    └───────────┬──────────────┘ │
+│                                                        │                 │
+│                                    ┌───────────────────┼───────────────┐ │
+│                                    ▼                   ▼               ▼ │
+│                           ┌───────────────┐  ┌─────────────┐  ┌──────────┐ │
+│                           │ DXA Classifier │  │  Segmentor │  │ Quality  │ │
+│                           │   (ResNet18)   │  │ (Threshold) │  │  Scorer  │ │
+│                           └───────────────┘  └─────────────┘  └──────────┘ │
+│                                                                          │
+│  ┌────────────────────────────────────────────────────────────────────┐  │
+│  │                    Detailed Assessment Module                      │  │
+│  │  ┌─────────┐  ┌──────────┐  ┌─────────┐  ┌───────┐  ┌────────┐ │  │
+│  │  │  Motion │  │ Artifact │  │ Position│  │  ROI  │  │Rotation│ │  │
+│  │  │Detector │  │ Detector │  │Validator│  │ Check │  │ Checker│ │  │
+│  │  └─────────┘  └──────────┘  └─────────┘  └───────┘  └────────┘ │  │
+│  └────────────────────────────────────────────────────────────────────┘  │
+│                                                                          │
+└─────────────────────────────────────────────────────────────────────────┘
+

Технологический стек

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
КомпонентТехнология
BackendPython 3.10, FastAPI, Uvicorn
ML/DLPyTorch, torchvision (ResNet18)
Image ProcessingPIL, OpenCV, pydicom, scipy
Data Handlingpandas, openpyxl
ContainerizationDocker
+
+

Компоненты системы

+

1. API Layer (src/main.py)

+

Точка входа — FastAPI приложение с REST эндпоинтами.

+

Основные функции:

+ +
# Основной API эндпоинт
+@app.post("/api/v1/analyze/detailed")
+async def analyze_dicom_detailed(file: UploadFile = File(...)):
+    # 1. Загрузка модели
+    # 2. Предобработка DICOM
+    # 3. Инференс ResNet18
+    # 4. Генерация сегментации
+    # 5. Детальная оценка качества
+    # 6. Формирование ответа
+

2. DXA Classifier (src/dxa/model.py)

+

Модель для бинарной классификации качества изображения.

+

Архитектура:

+
Input (224x224x3)
+    │
+    ▼
+ResNet18 (pretrained on ImageNet)
+    │
+    ├── Remove final FC layer
+    │
+    ▼
+Classifier Head:
+    ├── Dropout(0.3)
+    ├── Linear(512 → 256)
+    ├── ReLU
+    ├── Dropout(0.3)
+    └── Linear(256 → 2)
+    │
+    ▼
+Output: [prob_OK, prob_Violation]
+

Параметры модели:

+ +

3. Segmentator (Простая реализация)

+

Для сегментации используется простой пороговый метод:

+
# Threshold-based segmentation
+threshold = np.percentile(image, 90)
+segmentation = (image > threshold).astype(np.uint8)
+

Планируется: Замена на UNet или TotalSegmentator для более точной сегментации.

+

4. Detailed Assessment (src/quality/detailed_assessment.py)

+

Модуль детальной оценки качества включает:

+

4.1 Motion Detection

+ +

4.2 Artifact Detection

+ +

4.3 Region-Specific Checks

+

Для позвоночника (spine):

+ +

Для бедра (hip):

+ +

4.4 ROI Validation

+ +

5. Region Detector (src/dxa/inference.py)

+

Определение анатомической области по содержимому изображения:

+

Алгоритм:

+
    +
  1. Пороговая бинаризация (95 перцентиль)
  2. +
  3. Вычисление bounding box яркой области
  4. +
  5. Соотношение сторон bbox: +
      +
    • < 1.5 → spine (более квадратная область)
    • +
    • ≥ 1.5 → hip (вытянутая область)
    • +
    +
  6. +
  7. Для hip: определение левого/правого по асимметрии яркости
  8. +
+
+

Пайплайн обработки

+

Основной пайплайн

+

DXA Quality Assessment PipelineUpload DICOM fileParse DICOM metadata- Normalize to 0-1- Convert to 3-channel- Resize to 224x224Preprocess image- Get prediction (OK/Violation)- Get confidence scoresModel Inference (ResNet18)- bbox_aspect ratio analysis- left/right brightness ratioDetermine Anatomical Region- Threshold-based (90th percentile)Generate Segmentation- Motion detection- Artifact detection- Region-specific checks- ROI validationDetailed Quality Assessment- correct- position_error- artifact_motion- artifact_other- labeling_error- incomplete_view- roi_error- rotationDetermine Violation TypeGenerate Response

Детальная диаграмма последовательности

+

Sequence: Detailed AnalysisUserFastAPIDXA ModelRegion DetectorSegmentatorQuality AssessorUserUserFastAPIFastAPIDXA ModelDXA ModelRegion DetectorRegion DetectorSegmentatorSegmentatorQuality AssessorQuality AssessorPOST /api/v1/analyze/detailedpreprocess_dicom()predict(image)[prediction, confidence]determine_region(image)"spine" | "hip_left" | "hip_right"segment(image)segmentation_maskgenerate_quality_report()- detect_motion_blur()- detect_artifacts()- check_spine_completeness() / check_hip_completeness()- check_hip_rotation()- check_roi_boundaries()- determine_violation_type()quality_reportconvert_to_serializable()JSON response


+

API Endpoints

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MethodEndpointDescription
GET/Web interface
GET/api/v1/healthHealth check
POST/api/v1/analyzeBasic analysis
POST/api/v1/analyze/detailedDetailed analysis with metrics
POST/api/v1/analyze/srDICOM SR report
POST/api/v1/batchBatch processing
POST/api/v1/exportExport to XLSX
+

Response Format (Detailed)

+
{
+  "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.001,
+      "severity": "HIGH"
+    },
+    "artifacts": {
+      "any_detected": false,
+      "metal_detected": false
+    },
+    "roi_check": {
+      "valid": true
+    }
+  },
+  "overall_quality": "POOR",
+  "severity": "HIGH"
+}
+

+

Модели и алгоритмы

+

Типы нарушений

+

Для позвоночника:

+ +

Для бедра:

+ +

Метрики детекции движения

+ + + + + + + + + + + + + + + + + + + + + + + + + +
МетрикаПорогОписание
Laplacian variance< 0.002Низкая дисперсия = размытие
FFT high-freq ratio< 0.3Низкая высокочастотная энергия
Edge duplicationboolДублирование краев
+

Алгоритм определения региона

+

Error 400: Cannot find if (Assumed diagram type: activity) (line: 22)


+

PlantUML Диаграммы

+

Диаграмма компонентов

+

Web ClientFastAPI ServerDXA ModelsQuality AssessmentFile SystemWeb UIUpload HandlerPreprocessorResponse BuilderResNet18 ClassifierRegion DetectorSegmentatorMotion DetectorArtifact DetectorPosition ValidatorROI CheckerRotation CheckerDICOM FilesModel WeightsHTTPRead/WriteInferenceQuality Metrics

Диаграмма классов (основные сущности)

+

DXAQualityClassifierbackbone: strnum_classes: intforward(x: Tensor) -> Tensorextract_features(x: Tensor) -> TensorDXAQualityModelmodel: DXAQualityClassifierdevice: strpredict(images: Tensor) -> (preds, probs)train_epoch(loader)validate(loader)DetailedAssessmentdetect_motion_blur(image) -> Dictdetect_artifacts(image, segmentation) -> Dictcheck_spine_completeness(segmentation) -> Dictcheck_hip_completeness(segmentation) -> Dictcheck_hip_rotation(segmentation, image) -> Dictcheck_roi_boundaries(segmentation, shape) -> Dictgenerate_quality_report(...) -> DictRegionDetectordetermine_region_from_image(image) -> strdetermine_anatomical_region(dcm_path) -> strusesprovides region

Диаграмма развертывания

+

Client LayerApplication LayerML PipelineInfrastructureBrowserWeb UI (HTML/JS)FastAPIUvicornDXA ClassifierSegmentatorQuality AssessorCPU/GPUFile SystemDockerPyTorchNumPy/SciPyModels/Data


+

Потоки данных

+

InputPreprocessingML ModelsQuality AnalysisOutputDICOM FileNormalization3-Channel ConvResize 224x224ResNet18Region DetectorThreshold SegMotion DetectionArtifact DetectionCompleteness CheckROI ValidationJSON ResponseXLSX Export


+

Ограничения и планы развития

+

Текущие ограничения

+
    +
  1. Сегментация — простая пороговая обработка, требует замены на Deep Learning (UNet/TotalSegmentator)
  2. +
  3. Модель — бинарная классификация, нужно расширение до многоклассовой для типов нарушений
  4. +
  5. Dataset — ~100 исследований, требуется расширение до 500+
  6. +
  7. F1 Score — текущий ~0.27, требует улучшения
  8. +
+

Планируемые улучшения

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
КомпонентПлан
Region DetectorОтдельная модель для детекции региона
SegmentatorUNet или TotalSegmentator
Quality ClassifierРасширение на 8 классов нарушений
Violation ClassifierОтдельная модель для классификации типа нарушения
Artifact DetectorCNN для детекции металла/имплантатов
VisualizationGrad-CAM для внимания модели
+
+

Заключение

+

Система DXA Quality Assessment представляет собой полнофункциональный AI-сервис для автоматизированной оценки качества DXA исследований. Архитектура построена на принципах модульности и расширяемости, что позволяет поэтапно улучшать отдельные компоненты.

+

Основные характеристики:

+ + +
+ + + + + + + + + + \ No newline at end of file diff --git a/docs/architecture-analytical.md b/docs/architecture-analytical.md new file mode 100644 index 0000000..befc39a --- /dev/null +++ b/docs/architecture-analytical.md @@ -0,0 +1,652 @@ +# Аналитический документ: DXA Quality Assessment System + +## Содержание + +1. [Обзор системы](#обзор-системы) +2. [Архитектура](#архитектура) +3. [Компоненты системы](#компоненты-системы) +4. [Пайплайн обработки](#пайплайн-обработки) +5. [API Endpoints](#api-endpoints) +6. [Модели и алгоритмы](#модели-и-алгоритмы) +7. [PlantUML Диаграммы](#plantuml-диаграммы) + +--- + +## Обзор системы + +Система DXA Quality Assessment — это медицинский AI-сервис для автоматизированной оценки качества исследований DXA (денситометрия костей). Система анализирует DICOM файлы и определяет: + +- **Анатомическую область**: позвоночник (spine) или бедро (hip_left/hip_right) +- **Качество изображения**: OK (класс 0) или нарушение (класс 1) +- **Тип нарушения**: движение, артефакты, позиционирование, ROI, ротация + +### Целевое назначение + +| Параметр | Значение | +|----------|----------| +| Тип | Медицинский AI сервис | +| Входные данные | DICOM файлы (DXA исследования) | +| Выходные данные | JSON / XLSX отчеты | +| Тип классификации | Бинарный (OK / Violation) | +| Целевые регионы | Позвоночник (L1-L4), Бедро (левое/правое) | + +--- + +## Архитектура + +### Высокоуровневая архитектура + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ DXA Quality Assessment │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ +│ │ Клиент │───▶│ FastAPI │───▶│ Orchestrator │ │ +│ │ (Web UI) │ │ Server │ │ (Pipeline Control) │ │ +│ └──────────────┘ └──────────────┘ └───────────┬──────────────┘ │ +│ │ │ +│ ┌───────────────────┼───────────────┐ │ +│ ▼ ▼ ▼ │ +│ ┌───────────────┐ ┌─────────────┐ ┌──────────┐ │ +│ │ DXA Classifier │ │ Segmentor │ │ Quality │ │ +│ │ (ResNet18) │ │ (Threshold) │ │ Scorer │ │ +│ └───────────────┘ └─────────────┘ └──────────┘ │ +│ │ +│ ┌────────────────────────────────────────────────────────────────────┐ │ +│ │ Detailed Assessment Module │ │ +│ │ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌───────┐ ┌────────┐ │ │ +│ │ │ Motion │ │ Artifact │ │ Position│ │ ROI │ │Rotation│ │ │ +│ │ │Detector │ │ Detector │ │Validator│ │ Check │ │ Checker│ │ │ +│ │ └─────────┘ └──────────┘ └─────────┘ └───────┘ └────────┘ │ │ +│ └────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +### Технологический стек + +| Компонент | Технология | +|-----------|------------| +| Backend | Python 3.10, FastAPI, Uvicorn | +| ML/DL | PyTorch, torchvision (ResNet18) | +| Image Processing | PIL, OpenCV, pydicom, scipy | +| Data Handling | pandas, openpyxl | +| Containerization | Docker | + +--- + +## Компоненты системы + +### 1. API Layer (`src/main.py`) + +Точка входа — FastAPI приложение с REST эндпоинтами. + +**Основные функции:** +- Прием DICOM файлов через multipart/form-data +- Предобработка изображений (нормализация, ресайз до 224x224) +- Инференс модели +- Формирование ответов + +```python +# Основной API эндпоинт +@app.post("/api/v1/analyze/detailed") +async def analyze_dicom_detailed(file: UploadFile = File(...)): + # 1. Загрузка модели + # 2. Предобработка DICOM + # 3. Инференс ResNet18 + # 4. Генерация сегментации + # 5. Детальная оценка качества + # 6. Формирование ответа +``` + +### 2. DXA Classifier (`src/dxa/model.py`) + +Модель для бинарной классификации качества изображения. + +**Архитектура:** +``` +Input (224x224x3) + │ + ▼ +ResNet18 (pretrained on ImageNet) + │ + ├── Remove final FC layer + │ + ▼ +Classifier Head: + ├── Dropout(0.3) + ├── Linear(512 → 256) + ├── ReLU + ├── Dropout(0.3) + └── Linear(256 → 2) + │ + ▼ +Output: [prob_OK, prob_Violation] +``` + +**Параметры модели:** +- Backbone: ResNet18 (ImageNet pretrained) +- Input: 224x224 RGB +- Output: 2 класса (OK / Violation) +- Dropout: 0.3 + +### 3. Segmentator (Простая реализация) + +Для сегментации используется простой пороговый метод: + +```python +# Threshold-based segmentation +threshold = np.percentile(image, 90) +segmentation = (image > threshold).astype(np.uint8) +``` + +**Планируется:** Замена на UNet или TotalSegmentator для более точной сегментации. + +### 4. Detailed Assessment (`src/quality/detailed_assessment.py`) + +Модуль детальной оценки качества включает: + +#### 4.1 Motion Detection +- **Laplacian variance** — дисперсия лапласиана (ниже = размытие) +- **FFT blur** — анализ высокочастотной энергии (ниже = размытие) +- **Edge duplication** — проверка "призрачных" краев + +#### 4.2 Artifact Detection +- **Metal detection** — яркие пятна (>99.5 перцентиль) +- **Implant detection** — линейные структуры +- **Cement detection** — локальные яркие области +- **Calcification** — малые яркие пятна + +#### 4.3 Region-Specific Checks + +**Для позвоночника (spine):** +- Проверка количества позвонков (3-4 для поясничного отдела) +- Проверка полноты (не обрезаны ли позвонки) +- Проверка выравнивания позвонков +- Проверка контуров позвонков + +**Для бедра (hip):** +- Проверка полноты видимости (шейка бедра, головка) +- Проверка ротации (угол главной оси) +- Проверка соотношения сторон + +#### 4.4 ROI Validation +- Проверка отступов от краев +- Проверка размера ROI + +### 5. Region Detector (`src/dxa/inference.py`) + +Определение анатомической области по содержимому изображения: + +**Алгоритм:** +1. Пороговая бинаризация (95 перцентиль) +2. Вычисление bounding box яркой области +3. Соотношение сторон bbox: + - < 1.5 → **spine** (более квадратная область) + - ≥ 1.5 → **hip** (вытянутая область) +4. Для hip: определение левого/правого по асимметрии яркости + +--- + +## Пайплайн обработки + +### Основной пайплайн + +```plantuml +@startuml +title DXA Quality Assessment Pipeline + +start +:Upload DICOM file; +:Parse DICOM metadata; +:Preprocess image; + +note right + - Normalize to 0-1 + - Convert to 3-channel + - Resize to 224x224 +end note + +:Model Inference (ResNet18); +note right + - Get prediction (OK/Violation) + - Get confidence scores +end note + +:Determine Anatomical Region; +note right + - bbox_aspect ratio analysis + - left/right brightness ratio +end note + +:Generate Segmentation; +note right + - Threshold-based (90th percentile) +end note + +:Detailed Quality Assessment; + +note right + - Motion detection + - Artifact detection + - Region-specific checks + - ROI validation +end note + +:Determine Violation Type; + +note right + - correct + - position_error + - artifact_motion + - artifact_other + - labeling_error + - incomplete_view + - roi_error + - rotation +end note + +:Generate Response; +stop + +@enduml +``` + +### Детальная диаграмма последовательности + +```plantuml +@startuml +title Sequence: Detailed Analysis + +actor User +participant "FastAPI" as API +participant "DXA Model" as Model +participant "Region Detector" as Region +participant "Segmentator" as Seg +participant "Quality Assessor" as QA + +User -> API: POST /api/v1/analyze/detailed +API -> API: preprocess_dicom() +API -> Model: predict(image) +Model --> API: [prediction, confidence] + +API -> Region: determine_region(image) +Region --> API: "spine" | "hip_left" | "hip_right" + +API -> Seg: segment(image) +Seg --> API: segmentation_mask + +API -> QA: generate_quality_report() +note over QA + - detect_motion_blur() + - detect_artifacts() + - check_spine_completeness() / check_hip_completeness() + - check_hip_rotation() + - check_roi_boundaries() + - determine_violation_type() +end note + +QA --> API: quality_report + +API -> API: convert_to_serializable() +API --> User: JSON response + +@enduml +``` + +--- + +## API Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| GET | `/` | Web interface | +| GET | `/api/v1/health` | Health check | +| POST | `/api/v1/analyze` | Basic analysis | +| POST | `/api/v1/analyze/detailed` | Detailed analysis with metrics | +| POST | `/api/v1/analyze/sr` | DICOM SR report | +| POST | `/api/v1/batch` | Batch processing | +| POST | `/api/v1/export` | Export to XLSX | + +### Response Format (Detailed) + +```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.001, + "severity": "HIGH" + }, + "artifacts": { + "any_detected": false, + "metal_detected": false + }, + "roi_check": { + "valid": true + } + }, + "overall_quality": "POOR", + "severity": "HIGH" +} +``` + +--- + +## Модели и алгоритмы + +### Типы нарушений + +**Для позвоночника:** +- `correct` — качество соответствует норме +- `position_error` — ошибка позиционирования +- `artifact_motion` — артефакт движения (размытие) +- `artifact_other` — другие артефакты +- `labeling_error` — ошибка маркировки +- `incomplete_view` — неполный вид +- `roi_error` — ошибка ROI + +**Для бедра:** +- `correct` — качество соответствует норме +- `position_error` — ошибка позиционирования +- `rotation` — нарушение ротации +- `artifact_motion` — артефакт движения +- `artifact_other` — другие артефакты +- `roi_error` — ошибка ROI +- `incomplete_view` — неполный вид + +### Метрики детекции движения + +| Метрика | Порог | Описание | +|---------|-------|----------| +| Laplacian variance | < 0.002 | Низкая дисперсия = размытие | +| FFT high-freq ratio | < 0.3 | Низкая высокочастотная энергия | +| Edge duplication | bool | Дублирование краев | + +### Алгоритм определения региона + +```plantuml +@startuml +title Region Detection Algorithm + +start +:Load DICOM image; +:Normalize to 0-1; +:Threshold at 95th percentile; + +if (binary.sum > 0?) then (yes) + :Calculate bounding box; + :Compute bbox_aspect = height / width; + + if (bbox_aspect < 1.5) then (yes) + :return "spine"; + else (no) + if (bbox_aspect < 1.8) then (yes) + :Calculate symmetry; + if (symmetry > 0.35) then (yes) + :return "spine"; + else (no) + :return "hip"; + end + else (no) + :Calculate left/right brightness ratio; + + if (ratio > 1.3) then (yes) + :return "hip_right"; + else if (ratio < 0.7) then (yes) + :return "hip_left"; + else (no) + :return "hip"; + end + end + end +else (no) + :Fallback: height < 270 → hip; + :return "spine"; +end + +stop + +@enduml +``` + +--- + +## PlantUML Диаграммы + +### Диаграмма компонентов + +```plantuml +@startuml +!theme plain +skinparam componentStyle uml2 + +component "Web Client" as Client { + [Web UI] +} + +component "FastAPI Server" as API { + [Upload Handler] + [Preprocessor] + [Response Builder] +} + +component "DXA Models" as Models { + [ResNet18 Classifier] + [Region Detector] + [Segmentator] +} + +component "Quality Assessment" as QA { + [Motion Detector] + [Artifact Detector] + [Position Validator] + [ROI Checker] + [Rotation Checker] +} + +database "File System" as FS { + [DICOM Files] + [Model Weights] +} + +Client -down-> API : HTTP +API -down-> FS : Read/Write +API -right-> Models : Inference +Models -down-> QA : Quality Metrics + +@enduml +``` + +### Диаграмма классов (основные сущности) + +```plantuml +@startuml +!theme plain + +class DXAQualityClassifier { + +backbone: str + +num_classes: int + +forward(x: Tensor) -> Tensor + +extract_features(x: Tensor) -> Tensor +} + +class DXAQualityModel { + +model: DXAQualityClassifier + +device: str + +predict(images: Tensor) -> (preds, probs) + +train_epoch(loader) + +validate(loader) +} + +class DetailedAssessment { + +detect_motion_blur(image) -> Dict + +detect_artifacts(image, segmentation) -> Dict + +check_spine_completeness(segmentation) -> Dict + +check_hip_completeness(segmentation) -> Dict + +check_hip_rotation(segmentation, image) -> Dict + +check_roi_boundaries(segmentation, shape) -> Dict + +generate_quality_report(...) -> Dict +} + +class RegionDetector { + +determine_region_from_image(image) -> str + +determine_anatomical_region(dcm_path) -> str +} + +DXAQualityModel --> DXAQualityClassifier +DXAQualityModel ..> DetailedAssessment : uses +RegionDetector ..> DetailedAssessment : provides region + +@enduml +``` + +### Диаграмма развертывания + +```plantuml +@startuml +!theme plain +skinparam rectangle { + BackgroundColor #White + BorderColor #Black +} + +rectangle "Client Layer" { + rectangle "Browser" as Browser + rectangle "Web UI (HTML/JS)" as WebUI +} + +rectangle "Application Layer" { + rectangle "FastAPI" as API + rectangle "Uvicorn" as Uvicorn +} + +rectangle "ML Pipeline" { + rectangle "DXA Classifier" as Classifier + rectangle "Segmentator" as Segmentator + rectangle "Quality Assessor" as Assessor +} + +rectangle "Infrastructure" { + rectangle "CPU/GPU" as Compute + rectangle "File System" as Storage + rectangle "Docker" as Docker +} + +Browser -right-> WebUI +WebUI -right-> API +API -right-> Uvicorn +Uvicorn -right-> Classifier +Uvicorn -right-> Segmentator +Classifier -right-> Assessor +Classifier -up-> Compute : PyTorch +Segmentator -up-> Compute : NumPy/SciPy +API -down-> Storage : Models/Data +Compute -up-> Docker + +@enduml +``` + +--- + +## Потоки данных + +```plantuml +@startuml +!theme plain +skinparam ranksep 50 +skinparam nodesep 50 + +node "Input" { + [DICOM File] +} + +node "Preprocessing" { + [Normalization] + [3-Channel Conv] + [Resize 224x224] +} + +node "ML Models" { + [ResNet18] + [Region Detector] + [Threshold Seg] +} + +node "Quality Analysis" { + [Motion Detection] + [Artifact Detection] + [Completeness Check] + [ROI Validation] +} + +node "Output" { + [JSON Response] + [XLSX Export] +} + +[DICOM File] --> [Normalization] +[Normalization] --> [3-Channel Conv] +[3-Channel Conv] --> [Resize 224x224] + +[Resize 224x224] --> [ResNet18] +[Resize 224x224] --> [Region Detector] +[Resize 224x224] --> [Threshold Seg] + +[ResNet18] --> [Quality Analysis] +[Region Detector] --> [Quality Analysis] +[Threshold Seg] --> [Quality Analysis] + +[Quality Analysis] --> [JSON Response] +[Quality Analysis] --> [XLSX Export] + +@enduml +``` + +--- + +## Ограничения и планы развития + +### Текущие ограничения + +1. **Сегментация** — простая пороговая обработка, требует замены на Deep Learning (UNet/TotalSegmentator) +2. **Модель** — бинарная классификация, нужно расширение до многоклассовой для типов нарушений +3. **Dataset** — ~100 исследований, требуется расширение до 500+ +4. **F1 Score** — текущий ~0.27, требует улучшения + +### Планируемые улучшения + +| Компонент | План | +|-----------|------| +| Region Detector | Отдельная модель для детекции региона | +| Segmentator | UNet или TotalSegmentator | +| Quality Classifier | Расширение на 8 классов нарушений | +| Violation Classifier | Отдельная модель для классификации типа нарушения | +| Artifact Detector | CNN для детекции металла/имплантатов | +| Visualization | Grad-CAM для внимания модели | + +--- + +## Заключение + +Система DXA Quality Assessment представляет собой полнофункциональный AI-сервис для автоматизированной оценки качества DXA исследований. Архитектура построена на принципах модульности и расширяемости, что позволяет поэтапно улучшать отдельные компоненты. + +Основные характеристики: +- ✅ RESTful API с FastAPI +- ✅ Глубокое обучение (ResNet18) +- ✅ Детальная оценка качества с метриками +- ✅ Поддержка нескольких типов нарушений +- ✅ Экспорт в XLSX/CSV +- ✅ Docker контейнеризация diff --git a/docs/architecture-analytical.png b/docs/architecture-analytical.png new file mode 100644 index 0000000000000000000000000000000000000000..f3fd6ac12bc79127ac0156af5272bc8378dd7acd GIT binary patch literal 24267 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 cf!+qP}KeBb}w`|etAt-IGctE+d{ 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 PtO3&E3St!^`T_q3*?A?9 literal 0 HcmV?d00001 diff --git a/docs/architecture-analytical_003.png b/docs/architecture-analytical_003.png new file mode 100644 index 0000000000000000000000000000000000000000..9519af8ae7dd12db831543a047327cc1702da783 GIT binary patch literal 19986 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 x;KrM$pWAgZY-j=2.0.0 -torchvision>=0.15.0 -numpy>=1.24.0 - -# Image processing -Pillow>=10.0.0 -opencv-python-headless>=4.8.0 - -# Medical imaging -pydicom>=2.4.0 -pydicom-seg>=0.4.0 -nibabel>=5.0.0 -SimpleITK>=2.2.0 - -# Deep learning / models -torchvision>=0.15.0 -timm>=0.9.0 - -# Data handling -pandas>=2.0.0 -openpyxl>=3.1.0 - -# Visualization -matplotlib>=3.7.0 - -# API / serving -fastapi>=0.100.0 -uvicorn>=0.23.0 -python-multipart>=0.0.6 - -# Progress bars -tqdm>=4.65.0 - -# Utils -scipy>=1.10.0 -scikit-learn>=1.3.0 +annotated-doc==0.0.5 +annotated-types==0.7.0 +anyio==4.12.1 +attrs==26.1.0 +certifi==2026.7.22 +click==8.1.8 +contourpy==1.3.0 +cycler==0.12.1 +et_xmlfile==2.0.0 +exceptiongroup==1.3.1 +fastapi==0.128.8 +filelock==3.19.1 +fonttools==4.60.2 +fsspec==2025.10.0 +h11==0.16.0 +hf-xet==1.6.0 +httpcore==1.0.9 +httpx==0.28.1 +huggingface_hub==1.8.0 +idna==3.18 +importlib_resources==6.5.2 +Jinja2==3.1.6 +joblib==1.5.3 +jsonschema==3.2.0 +kiwisolver==1.4.7 +markdown-it-py==3.0.0 +MarkupSafe==3.0.3 +matplotlib==3.9.4 +mdurl==0.1.2 +monai==1.5.2 +mpmath==1.3.0 +networkx==3.2.1 +nibabel==5.3.3 +numpy==1.26.4 +opencv-python-headless==4.11.0.86 +openpyxl==3.1.5 +packaging==26.3 +pandas==2.3.3 +pillow==11.3.0 +pydantic==2.13.4 +pydantic_core==2.46.4 +pydicom==2.4.4 +pydicom-seg==0.4.1 +Pygments==2.21.0 +pyparsing==3.3.2 +pyrsistent==0.20.0 +python-dateutil==2.9.0.post0 +python-multipart==0.0.20 +pytz==2026.3.post1 +PyYAML==6.0.3 +rich==15.0.0 +safetensors==0.7.0 +scikit-learn==1.6.1 +scipy==1.13.1 +shellingham==1.5.4 +simpleitk==2.5.6 +six==1.17.0 +starlette==0.49.3 +sympy==1.14.0 +threadpoolctl==3.7.0 +timm==1.0.29 +torch==2.8.0 +torchvision==0.23.0 +TotalSegmentator==2.18.0 +tqdm==4.70.0 +typer==0.23.2 +typing-inspection==0.4.2 +typing_extensions==4.16.0 +tzdata==2026.3 +unicorn==2.1.4 +uvicorn==0.39.0 +zipp==3.23.1 diff --git a/src/api/static/index.html b/src/api/static/index.html index 6cef7de..548dbf8 100644 --- a/src/api/static/index.html +++ b/src/api/static/index.html @@ -256,7 +256,20 @@ -
+
+ +
+ +
+ + +
+

Идентификаторы

+
+ +
+
+
@@ -265,7 +278,7 @@
- +

Детали качества

@@ -273,33 +286,101 @@
- - -
-

Метрики

-
+ + +
+

Уверенность модели

+
- - -
-

Причина

-
+ + +
+

Общая оценка

+
- - -
-

Визуализация

-
-
-

Оригинал

-
-
-

Маска ROI

-
+ + +
+

+ Движение (Motion) +

+
+ +
+
+ + +
+

+ Артефакты +

+
+ +
+
+ + +
+

+ Позиция +

+
+ +
+
+ + +
+

+ ROI +

+
+ +
+
+ + + + + + +
+ + +
+

Заключение

+
+ +
+
+ + +
+

Визуализация

+
+
+

Оригинал

+
+
+

Маска ROI

diff --git a/src/api/static/js/dxa-app.js b/src/api/static/js/dxa-app.js index b2a86ad..31b4b8f 100644 --- a/src/api/static/js/dxa-app.js +++ b/src/api/static/js/dxa-app.js @@ -359,74 +359,265 @@ document.getElementById('closeDetail')?.addEventListener('click', () => { // View detailed analysis for a file async function viewDetail(result) { detailSection.classList.remove('hidden'); - - // Populate basic info - const regionLabel = result.anatomical_region === 'spine' ? 'Позвоночник' : - result.anatomical_region === 'hip_left' ? 'Бедро левое' : - result.anatomical_region === 'hip_right' ? 'Бедро правое' : - result.anatomical_region === 'hip' ? 'Бедро' : result.anatomical_region || '—'; - - document.getElementById('detailBasic').innerHTML = ` -
Файл:${result.filename || '—'}
-
Регион:${regionLabel}
-
UID исследования:${(result.study_uid || '').substring(0, 20)}...
- `; - - // Populate quality details + + // Region label helper + const getRegionLabel = (region) => { + const labels = { + 'spine': 'Позвоночник', + 'hip_left': 'Бедро левое', + 'hip_right': 'Бедро правое', + 'hip': 'Бедро (общее)', + 'unknown': 'Неизвестно' + }; + return labels[region] || region || '—'; + }; + + // Violation type label + const getViolationLabel = (type) => { + const labels = { + 'correct': 'Корректно', + 'position_error': 'Ошибка позиционирования', + 'artifact_motion': 'Артефакт движения', + 'artifact_other': 'Другие артефакты', + 'labeling_error': 'Ошибка маркировки', + 'incomplete_view': 'Неполный вид', + 'roi_error': 'Ошибка ROI', + 'rotation': 'Неправильный поворот' + }; + return labels[type] || type || '—'; + }; + + // Quality badge const qualityClass = result.quality_class === 0 ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400' : result.quality_class === 1 ? 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400' : 'bg-gray-100 text-gray-800'; - - const violationType = result.violation_type || (result.quality_class === 1 ? 'quality_violation_detected' : 'correct'); - const reason = result.reason || (result.quality_class === 0 ? 'Качество соответствует норме' : 'Нарушение качества'); - - document.getElementById('detailQuality').innerHTML = ` -
Класс:${result.quality_class === 0 ? 'OK' : 'Нарушение'}
-
Тип нарушения:${violationType}
-
Уверенность:${result.confidence ? (result.confidence * 100).toFixed(1) + '%' : '—'}
-
Вид:${result.view_quality || 'unknown'}
+ const qualityLabel = result.quality_class === 0 ? 'OK' : result.quality_class === 1 ? 'Нарушение' : 'Ошибка'; + + document.getElementById('detailBadge').innerHTML = ` + + ${qualityLabel} + + ${result.quality_label || ''} `; - - // Populate metrics + + // UIDs + document.getElementById('detailUIDs').innerHTML = ` +
Study UID:${result.study_uid || '—'}
+
Image UID:${result.image_uid || '—'}
+ `; + + // Basic info + document.getElementById('detailBasic').innerHTML = ` +
Файл:${result.filename || '—'}
+
Регион:${getRegionLabel(result.anatomical_region)}
+
Вид снимка:${result.view_quality || 'unknown'}
+ `; + + // Quality details + document.getElementById('detailQuality').innerHTML = ` +
Тип нарушения:${getViolationLabel(result.violation_type)}
+
Класс:${result.quality_class}
+ `; + + // Confidence + const confCorrect = result.confidence_per_class?.correct || 0; + const confViolation = result.confidence_per_class?.violation || 0; + document.getElementById('detailConfidence').innerHTML = ` +
+
Верный:${(confCorrect * 100).toFixed(1)}%
+
+
+
+
Нарушение:${(confViolation * 100).toFixed(1)}%
+
+
+
+
+ `; + + // Overall quality + const overallClass = result.overall_quality === 'GOOD' ? 'text-green-600' : + result.overall_quality === 'FAIR' ? 'text-yellow-600' : + result.overall_quality === 'POOR' ? 'text-red-600' : 'text-gray-600'; + const severityClass = result.severity === 'LOW' ? 'bg-green-100 text-green-800 dark:bg-green-900/30' : + result.severity === 'MEDIUM' ? 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30' : + result.severity === 'HIGH' ? 'bg-red-100 text-red-800 dark:bg-red-900/30' : 'bg-gray-100'; + + document.getElementById('detailOverall').innerHTML = ` +
Качество:${result.overall_quality || '—'}
+
Серьёзность:${result.severity || '—'}
+ `; + + // Motion metrics const metrics = result.metrics || {}; const motion = metrics.motion || {}; - const artifacts = metrics.artifacts || {}; - const roi = metrics.roi_check || {}; - - document.getElementById('detailMetrics').innerHTML = ` + const blurLaplacian = motion.blur_laplacian?.toFixed(4) || '—'; + const blurFFT = motion.blur_fft?.toFixed(4) || '—'; + + document.getElementById('detailMotion').innerHTML = `
Движение
- ${motion.motion_detected ? 'Обнаружено' : 'Нет'} + ${motion.motion_detected ? 'Да' : 'Нет'}
- ${motion.severity ? `
Severity: ${motion.severity}
` : ''}
-
Артефакты
-
-
- ${artifacts.any_detected ? 'Обнаружены' : 'Нет'} -
- ${artifacts.metal_detected ? `
Металл: да
` : ''} - ${artifacts.implant_detected ? `
Имплантат: да
` : ''} +
Blur Laplacian
+ ${blurLaplacian} + ${motion.is_blurred_laplacian ? 'размыто' : ''}
-
ROI
+
Blur FFT
+ ${blurFFT} + ${motion.is_blurred_fft ? 'размыто' : ''} +
+
+
Дублирование краёв
-
- ${roi.valid === false ? 'Проблема' : 'OK'} +
+ ${motion.edge_duplication ? 'Да' : 'Нет'}
`; - - // Populate reason - const reasonClass = result.quality_class === 0 ? 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200' : - 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200'; + + // Artifacts + const artifacts = metrics.artifacts || {}; + document.getElementById('detailArtifacts').innerHTML = ` +
+
Металл
+
+
+ ${artifacts.metal_detected ? 'Да' : 'Нет'} +
+
+
+
Имплантат
+
+
+ ${artifacts.implant_detected ? 'Да' : 'Нет'} +
+
+
+
Цемент
+
+
+ ${artifacts.cement_detected ? 'Да' : 'Нет'} +
+
+
+
Кальцификаты
+
+
+ ${artifacts.calcification_detected ? 'Да' : 'Нет'} +
+
+
+
Локальные дефекты
+
+
+ ${artifacts.local_defects?.length || 0} +
+
+ `; + + // Position + const position = metrics.position || {}; + const posValid = position.valid !== false; + document.getElementById('detailPosition').innerHTML = ` +
Центр:${position.center_pixels ? `[${position.center_pixels[0]}, ${position.center_pixels[1]}]` : '—'}
+
Отклонение:${position.deviation?.toFixed(4) || '—'}
+
Размер объекта:${position.object_size?.toFixed(4) || '—'}
+
Валидность:${posValid ? 'OK' : 'Ошибка'}
+ `; + + // ROI + const roi = metrics.roi_check || {}; + const roiValid = roi.valid !== false; + document.getElementById('detailROI').innerHTML = ` +
Валидность:${roiValid ? 'OK' : 'Проблема'}
+
Размер:${roi.size ? `${roi.size.width}x${roi.size.height}` : '—'}
+
BBox:${roi.bounding_box ? `x:${roi.bounding_box.x_min}-${roi.bounding_box.x_max}, y:${roi.bounding_box.y_min}-${roi.bounding_box.y_max}` : '—'}
+ ${roi.issues?.length ? `
Проблемы:
    ${roi.issues.map(i => `
  • ${i}
  • `).join('')}
` : ''} + `; + + // Spine completeness + const spine = result.spine_completeness || {}; + const spineSection = document.getElementById('spineSection'); + if (spine && Object.keys(spine).length > 0) { + spineSection.classList.remove('hidden'); + document.getElementById('detailSpine').innerHTML = ` +
+
Позвонков
+ ${spine.vertebrae_count || '—'} +
+
+
Полный вид
+
+
+ ${spine.is_complete ? 'Да' : 'Нет'} +
+
+
+
Валидность
+
+
+ ${spine.valid ? 'OK' : 'Ошибка'} +
+
+
+
Проблемы
+ ${spine.issues?.length || 0} +
+ `; + } else { + spineSection.classList.add('hidden'); + } + + // Hip completeness + const hip = result.hip_completeness || {}; + const hipRotation = result.hip_rotation || {}; + const hipSection = document.getElementById('hipSection'); + if ((hip && Object.keys(hip).length > 0) || (hipRotation && Object.keys(hipRotation).length > 0)) { + hipSection.classList.remove('hidden'); + document.getElementById('detailHip').innerHTML = ` +
+
Полный вид
+
+
+ ${hip.is_complete ? 'Да' : 'Нет'} +
+
+
+
Соотношение сторон
+ ${hip.aspect_ratio?.toFixed(2) || '—'} +
+
+
Угол поворота
+ ${hipRotation.angle ? hipRotation.angle.toFixed(1) + '°' : '—'} +
+
+
Валидность
+
+
+ ${(hip.valid && hipRotation.valid) ? 'OK' : 'Ошибка'} +
+
+ `; + } else { + hipSection.classList.add('hidden'); + } + + // Reason + const reasonClass = result.quality_class === 0 ? 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200 border border-green-200 dark:border-green-800' : + 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200 border border-red-200 dark:border-red-800'; document.getElementById('detailReason').innerHTML = ` - ${reason} + + + ${result.reason || (result.quality_class === 0 ? 'Качество соответствует норме' : 'Нарушение качества')} + `; - + // Scroll to detail detailSection.scrollIntoView({ behavior: 'smooth' }); } diff --git a/src/training/train_model.py b/src/training/train_model.py index b574ef0..0e1d501 100644 --- a/src/training/train_model.py +++ b/src/training/train_model.py @@ -203,7 +203,7 @@ def main(): parser = argparse.ArgumentParser() parser.add_argument('--data-root', default='dataset_hack/НД_для_обучения') parser.add_argument('--annotation', default='dataset_hack/НД_для_обучения/разметка.xlsx') - parser.add_argument('--model-type', default='quality', choices=['quality', 'region', 'violation']) + parser.add_argument('--model-type', default='violation', choices=['quality', 'region', 'violation']) parser.add_argument('--epochs', type=int, default=15) parser.add_argument('--batch-size', type=int, default=8) parser.add_argument('--lr', type=float, default=1e-4)