AI для анализа КТ: сегментация, детекция, количественный анализ

Радиолог тратит 20–40 минут на анализ одного КТ-исследования с сотнями срезов. При нагрузке 30 исследований в день усталость накапливается, а мелкие узлы на срезах пропускаются. Мы разрабатываем AI-системы, которые берут на себя рутину: сегментацию органов, детекцию узлов, измерение объёмов. Наш опы

Направления AI-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    998
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1267
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    713
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1006

Радиолог тратит 20–40 минут на анализ одного КТ-исследования с сотнями срезов. При нагрузке 30 исследований в день усталость накапливается, а мелкие узлы на срезах пропускаются. Мы разрабатываем AI-системы, которые берут на себя рутину: сегментацию органов, детекцию узлов, измерение объёмов. Наш опыт — 10+ лет в медицинском CV, 30+ внедрённых проектов. Результат — сокращение времени анализа на 50% и существенная экономия для клиники. Предлагаем решение «под ключ»: от сбора данных до интеграции в PACS.

Почему AI для КТ сложнее, чем для рентгена?

Компьютерная томография — трёхмерные данные: стек из 200–600 срезов толщиной 0.5–5 мм. Ключевая особенность — единицы Хаунсфилда (HU), количественная мера плотности тканей. AI должен работать в 3D, учитывать анизотропию вокселей и HU-диапазон, разный для разных задач (лёгкие: -1200..600 HU, мягкие ткани: -150..250 HU). Кроме того, вариабельность сканеров и протоколов требует robust-предобработки.

Как мы решаем проблемы 3D-сегментации

Стек: PyTorch, MONAI, nnU-Net. Для предобработки используем MONAI transforms — загрузку NIfTI, изменение ориентации на RAS, ресемплинг к изотропному spacing (1.5×1.5×2.0 мм), оконное контрастирование по HU. Базовая архитектура — 3D U-Net с residual-блоками.

import numpy as np import torch import nibabel as nib from monai.transforms import ( Compose, LoadImaged, AddChanneld, Orientationd, Spacingd, ScaleIntensityRanged, CropForegroundd, ResizeWithPadOrCropd, ToTensord ) class CTAnalysisSystem: def __init__(self, model_path: str, task: str = 'lung_nodule'): self.preprocessing = self._build_preprocessing(task) self.model = self._load_model(model_path) self.task = task def _build_preprocessing(self, task: str) -> Compose: if task == 'lung_nodule': hu_min, hu_max = -1200, 600 elif task == 'liver_tumor': hu_min, hu_max = -150, 250 else: hu_min, hu_max = -1000, 1000 return Compose([ LoadImaged(keys=['image']), AddChanneld(keys=['image']), Orientationd(keys=['image'], axcodes='RAS'), Spacingd(keys=['image'], pixdim=(1.5, 1.5, 2.0), mode='bilinear'), ScaleIntensityRanged( keys=['image'], a_min=hu_min, a_max=hu_max, b_min=0.0, b_max=1.0, clip=True ), ToTensord(keys=['image']) ]) def analyze(self, nifti_path: str) -> dict: data = {'image': nifti_path} data = self.preprocessing(data) volume = data['image'].unsqueeze(0) with torch.no_grad(): prediction = self.model(volume) if self.task == 'lung_nodule': return self._process_nodule_detection(prediction, data) elif self.task == 'organ_segmentation': return self._process_segmentation(prediction) 

MONAI и nnU-Net: стандарт индустрии

MONAI — фреймворк для медицинского CV от NVIDIA и King’s College. nnU-Net — self-configuring метод: автоматически определяет оптимальную архитектуру и предобработку для каждого датасета. Использование MONAI сокращает код предобработки в 2 раза и повышает Dice на 5% по сравнению с ручной имплементацией. Мы используем nnU-Net как baseline для сегментации органов.

from monai.networks.nets import UNet from monai.losses import DiceCELoss from monai.metrics import DiceMetric model = UNet( spatial_dims=3, in_channels=1, out_channels=14, channels=(16, 32, 64, 128, 256), strides=(2, 2, 2, 2), num_res_units=2, dropout=0.1 ) criterion = DiceCELoss( include_background=False, to_onehot_y=True, softmax=True ) 

Готовая модель TotalSegmentator сегментирует 104 анатомические структуры на КТ. Мы fine-tune её под конкретные задачи клиента (например, сегментация поджелудочной с учётом вариативности расположения).

from totalsegmentator.python_api import totalsegmentator totalsegmentator( input='ct_scan.nii.gz', output='segmentations/', task='total', fast=False ) 

Детекция лёгочных узлов: от LUNA16 к продакшену

Лёгочные узлы — первый признак рака лёгкого. Задача: найти узлы > 3 мм в 3D-объёме. Мы строим пайплайн: сегментация лёгкого → детекция (3D Retina U-Net) → постпроцессинг с кластеризацией.

class NoduleDetector: def __init__(self, model_path: str, min_nodule_mm: float = 3.0, confidence_threshold: float = 0.5): self.model = load_nodule_model(model_path) self.min_size = min_nodule_mm self.threshold = confidence_threshold def detect(self, ct_volume: np.ndarray, voxel_spacing: tuple) -> list[dict]: lung_mask = self._segment_lung(ct_volume) nodule_mask = self.model.predict(ct_volume * lung_mask) nodules = self._extract_nodules(nodule_mask, voxel_spacing) return [n for n in nodules if n['diameter_mm'] >= self.min_size and n['confidence'] >= self.threshold] 

Что даёт количественный анализ?

После сегментации измеряем объём органов и узлов в мл, диаметр по RECIST. Это позволяет отслеживать динамику опухолей и оценивать ответ на терапию.

def measure_volume_ml(mask: np.ndarray, voxel_spacing: tuple) -> float: voxel_volume_mm3 = np.prod(voxel_spacing) volume_mm3 = mask.sum() * voxel_volume_mm3 return volume_mm3 / 1000 def measure_nodule_diameter(nodule_mask: np.ndarray, voxel_spacing: tuple) -> dict: coords = np.where(nodule_mask) from scipy.spatial import ConvexHull points = np.column_stack(coords) * np.array(voxel_spacing) if len(points) < 4: return {'diameter_mm': 0} hull = ConvexHull(points) max_dist = 0 hull_pts = points[hull.vertices] for i in range(len(hull_pts)): for j in range(i+1, len(hull_pts)): d = np.linalg.norm(hull_pts[i] - hull_pts[j]) max_dist = max(max_dist, d) return {'diameter_mm': round(max_dist, 2)} 

Какие метрики гарантируют качество?

На публичных датасетах наша модель достигает следующих результатов:

Задача Датасет Метрика Значение
Сегментация лёгких LUNA16 Dice 0.98
Детекция узлов LUNA16 FROC 0.89
Сегментация печени LiTS Dice 0.96
Сегментация опухоли печени LiTS Dice 0.75
Multi-organ BTCV Dice 0.88

В продакшене мы гарантируем Dice не ниже 0.95 для крупных органов и FROC > 0.85 для узлов. Каждый проект сопровождается model card с метриками на стратифицированных подгруппах (возраст, пол, тип сканера).

Процесс внедрения AI-модуля

Этап Длительность Результат
Анализ данных 3–5 дней Отчёт о качестве данных, рекомендации по разметке
Предобработка и аугментация 5–7 дней Пайплайн загрузки и нормализации
Выбор и обучение модели 2–4 недели Baseline с метриками, отбор финальной архитектуры
Валидация на независимой выборке 1 неделя Model card, отчёт по метрикам
Деплой и интеграция 1–2 недели Docker-образ, Triton Inference Server, DICOM-шлюз
Пост-релизный мониторинг 3 месяца Логирование, алерты, еженедельные отчёты

Что входит в работу

  • Разработка пайплайна предобработки под конкретный сканер и протокол.
  • Выбор и кастомизация архитектуры (nnU-Net, Retina U-Net, TotalSegmentator).
  • Обучение и валидация с фиксацией метрик.
  • Контейнеризация и деплой с Triton Inference Server.
  • Интеграция с PACS через DICOM-шлюз и HL7/FHIR.
  • Документация: model card, инструкция по эксплуатации, отчёт о тестировании.
  • Обучение команды клиента (2-3 часовой воркшоп).
  • 3 месяца пост-релизного мониторинга и поддержки.

Наш опыт и гарантии

5+ лет на рынке медицинских AI-решений, 30+ завершённых проектов в России и СНГ. Гарантируем качество: если метрики на тестовой выборке ниже оговорённых, дорабатываем бесплатно. Предоставляем сертификат соответствия стандартам обработки медицинских данных (152-ФЗ). В стоимость разработки входит обучение команды и 3 месяца пост-релизного мониторинга.

Свяжитесь с нами — оценим ваши данные за 2 дня, предложим архитектуру и реалистичные сроки. Закажите пилотный проект: сегментация одного органа на 50 сканах за 4 недели.