Разработка AI для анализа рентгеновских снимков
Рентгеновские снимки — наиболее массовый тип медицинской визуализации. Ежегодно в мире делается более 3 миллиардов рентгеновских исследований. AI-анализ решает задачи: выявление патологий на рентгенограммах органов грудной клетки (пневмония, узлы, отёк), анализ костей (переломы, изменения при остеопорозе), стоматологический рентген (кариес, периодонтит, патологии корней).
Анализ рентгена грудной клетки (CXR)
CheXNet (2017) стал поворотным моментом: DenseNet-121, обученный на 112,120 снимках CheXpert, превзошёл среднего радиолога по ряду патологий.
import torch
import torch.nn as nn
import torchvision.models as models
from torchvision import transforms
from PIL import Image
import numpy as np
class ChestXRayAnalyzer:
PATHOLOGIES = [
'Atelectasis', 'Cardiomegaly', 'Consolidation', 'Edema',
'Enlarged_Cardiomediastinum', 'Fracture', 'Lung_Lesion',
'Lung_Opacity', 'No_Finding', 'Pleural_Effusion',
'Pleural_Other', 'Pneumonia', 'Pneumothorax', 'Support_Devices'
]
def __init__(self, model_path: str, threshold: float = 0.5):
# DenseNet-121 как base
self.model = models.densenet121(pretrained=False)
self.model.classifier = nn.Sequential(
nn.Linear(self.model.classifier.in_features,
len(self.PATHOLOGIES)),
# НЕ sigmoid — используем BCEWithLogitsLoss при обучении
)
self.model.load_state_dict(torch.load(model_path))
self.model.eval()
self.threshold = threshold
self.transform = transforms.Compose([
transforms.Resize((320, 320)),
transforms.Grayscale(3), # CXR → 3 канала для ImageNet pretrained
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
@torch.no_grad()
def analyze(self, dicom_path: str) -> dict:
import pydicom
dcm = pydicom.dcmread(dicom_path)
pixel_array = dcm.pixel_array
# Нормализация pixel values
if dcm.PhotometricInterpretation == 'MONOCHROME1':
pixel_array = pixel_array.max() - pixel_array
pixel_norm = ((pixel_array - pixel_array.min()) /
(pixel_array.max() - pixel_array.min()) * 255).astype(np.uint8)
image = Image.fromarray(pixel_norm)
tensor = self.transform(image).unsqueeze(0)
logits = self.model(tensor)
probs = torch.sigmoid(logits).squeeze().numpy()
pathology_scores = {
path: float(prob)
for path, prob in zip(self.PATHOLOGIES, probs)
}
detected = {k: v for k, v in pathology_scores.items()
if v > self.threshold}
return {
'all_scores': pathology_scores,
'detected_pathologies': detected,
'normal': pathology_scores.get('No_Finding', 0) > self.threshold,
'critical_findings': self._check_critical(pathology_scores)
}
def _check_critical(self, scores: dict) -> list:
critical_threshold = 0.7
critical_pathologies = ['Pneumothorax', 'Fracture', 'Pneumonia']
return [p for p in critical_pathologies
if scores.get(p, 0) > critical_threshold]
Grad-CAM визуализация
Объяснение «почему модель так решила» критично для доверия врача:
from pytorch_grad_cam import GradCAM
from pytorch_grad_cam.utils.image import show_cam_on_image
class XRayExplainer:
def __init__(self, model: nn.Module):
target_layers = [model.features.denseblock4.denselayer16.conv2]
self.cam = GradCAM(model=model, target_layers=target_layers)
def explain(self, input_tensor: torch.Tensor,
target_class: int) -> np.ndarray:
grayscale_cam = self.cam(
input_tensor=input_tensor,
targets=[ClassifierOutputTarget(target_class)]
)
return grayscale_cam[0]
Публичные датасеты
| Датасет | Снимков | Патологии | Источник |
|---|---|---|---|
| CheXpert | 224k | 14 классов | Stanford |
| NIH ChestXray14 | 112k | 14 классов | NIH |
| MIMIC-CXR | 227k | 14 классов | MIT |
| PadChest | 160k | 174 радиологических наблюдения | Испания |
| VinBigData Chest XR | 18k с bbox | 14 патологий | Вьетнам |
Ограничения и регуляторика
Разработанная система выступает как Computer-Aided Detection (CAD) — инструмент поддержки принятия решений, не замена диагноза. Радиолог принимает окончательное решение. В России применение медицинских AI-систем регулируется Росздравнадзором, требуется регистрация как медицинское изделие для клинического применения.
| Задача | Срок |
|---|---|
| Классификатор 14 патологий (CXR) | 8–12 недель |
| Детекция патологий с bbox | 10–16 недель |
| Валидация + подготовка к регистрации | 20–40 недель |







