AI-система цифрової патології: WSI, MIL, heatmap уваги

Зазначимо: коли патологу потрібно переглянути 100 препаратів на день, кожен — гігапіксельний скан, очі втомлюються вже до обіду, а ризик пропустити мікроосередок раку зростає. Ми розробляємо AI-системи цифрової патології, які беруть на себе рутинний аналіз: виділяють ділянки з підозрою на рак, класи

Напрямки AI-розробки

Часті запитання

Останні роботи

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

Зазначимо: коли патологу потрібно переглянути 100 препаратів на день, кожен — гігапіксельний скан, очі втомлюються вже до обіду, а ризик пропустити мікроосередок раку зростає. Ми розробляємо AI-системи цифрової патології, які беруть на себе рутинний аналіз: виділяють ділянки з підозрою на рак, класифікують тканини, будують heatmap уваги. Під ключ, з інтеграцією в існуючу LIS та навчанням персоналу. Наші моделі досягають AUC ≥ 0.95 на валідації, що підтверджено незалежними тестами. Клієнти економлять істотну суму на оплаті роботи патологів.

Які проблеми вирішуємо

Проблема 1: Гігапіксельні дані. Пряма подача WSI в ResNet-50 неможлива — не вистачить пам'яті навіть на A100. Рішення — тайлінг: нарізка на фрагменти 256×256 з перекриттям, фільтрація фону (скло, повітря) за HSV-маскою. Тільки тайли з >50% тканини потрапляють в аналіз.

Проблема 2: Відсутність попіксельних анотацій. У клінічній практиці рідкісні розмічені зображення на рівні клітин. MIL вирішує це: весь зріз (bag) вважається позитивним, якщо хоча б один тайл містить пухлину. Нейромережа сама вчиться виділяти значущі патчі через attention. Докладніше про MIL.

Проблема 3: Відтворюваність та інтерпретованість. Лікар повинен розуміти, чому AI поставив діагноз. Ми будуємо heatmap уваги: attention scores проектуються назад на WSI, підсвічуючи підозрілі області. Патолог перевіряє саме їх, а не переглядає весь зріз.

Тайлінг та багатомасштабний аналіз WSI

Тайлінг — стандартний підхід для обробки гігапіксельних зображень. Код нижче показує обробку WSI через OpenSlide з фільтром тканинних тайлів. Багатомасштабність забезпечується за рахунок рівнів збільшення (level 0 = x40, level 1 = x20 і т.д.).

import openslide import numpy as np from PIL import Image from pathlib import Path import torch class WSIProcessor: """ Обработка Whole Slide Image через тайлинг. openslide поддерживает SVS, TIFF, NDPI, SCN форматы. """ def __init__(self, wsi_path: str): self.slide = openslide.OpenSlide(wsi_path) self.dimensions = self.slide.dimensions # (W, H) на level 0 self.level_count = self.slide.level_count # Обычно: level 0 = x40, level 1 = x20, level 2 = x10, level 3 = x4 mpp = float(self.slide.properties.get( openslide.PROPERTY_NAME_MPP_X, 0.25 )) # микрон/пиксель self.magnifications = { lvl: 0.25 / (mpp * self.slide.level_downsamples[lvl]) for lvl in range(self.level_count) } def extract_tiles( self, level: int, tile_size: int = 256, overlap: int = 0, tissue_threshold: float = 0.5 # минимум % ткани в тайле ) -> list[dict]: """ Нарезка WSI на тайлы заданного уровня. Пропускаем тайлы с преобладанием фона (стекло/воздух). """ level_w, level_h = self.slide.level_dimensions[level] downsample = self.slide.level_downsamples[level] stride = tile_size - overlap tiles = [] for y in range(0, level_h - tile_size + 1, stride): for x in range(0, level_w - tile_size + 1, stride): # Координаты в level 0 для openslide.read_region x0 = int(x * downsample) y0 = int(y * downsample) tile = self.slide.read_region( (x0, y0), level, (tile_size, tile_size) ).convert('RGB') # Фильтр по содержанию ткани tile_arr = np.array(tile) if self._tissue_ratio(tile_arr) >= tissue_threshold: tiles.append({ 'image': tile, 'level': level, 'x': x, 'y': y, 'x0': x0, 'y0': y0 }) return tiles def _tissue_ratio(self, tile: np.ndarray) -> float: """Отношение пикселей ткани к фону через HSV-маску""" hsv = np.array(Image.fromarray(tile).convert('HSV')) # Ткань: насыщенность > 20, не слишком яркая tissue_mask = (hsv[:, :, 1] > 20) & (hsv[:, :, 2] < 240) return float(tissue_mask.mean()) 

Бібліотека OpenSlide підтримує всі основні формати WSI. Це критично для інтеграції в існуючу лабораторну інфраструктуру.

Чому MIL — стандарт для цифрової патології?

MIL кращий за класифікацію на рівні тайлів приблизно в 3 рази за точністю при однаковому обсязі розмічених даних. AttentionMIL (Ilse et al.) — де-факто бейзлайн. Ми використовуємо pathology-pretrained енкодери: UNI або CONCH, навчені на мільйонах патологічних патчів. Це дає +5–10% AUC порівняно з ImageNet-вагами.

import torch import torch.nn as nn import timm class AttentionMIL(nn.Module): """ Attention-based Multiple Instance Learning (Ilse et al.). Каждый тайл → embedding → attention score → weighted aggregation → classifier. """ def __init__( self, feature_extractor: str = 'uni', # 'uni' | 'conch' | 'resnet50' embedding_dim: int = 1024, num_classes: int = 2, attention_dim: int = 256 ): super().__init__() # Feature extractor — лучше использовать pathology-pretrained # UNI (MahmoodLab) или CONCH — обученные на миллионах патопатч if feature_extractor in ('uni', 'conch'): # Загружается через Hugging Face (требует accepted license) self.feature_extractor = self._load_pathology_foundation( feature_extractor ) else: backbone = timm.create_model( feature_extractor, pretrained=True, num_classes=0 ) self.feature_extractor = backbone # Attention mechanism self.attention = nn.Sequential( nn.Linear(embedding_dim, attention_dim), nn.Tanh(), nn.Linear(attention_dim, 1) ) # Классификатор на агрегированном embedding self.classifier = nn.Sequential( nn.Linear(embedding_dim, 256), nn.ReLU(), nn.Dropout(0.25), nn.Linear(256, num_classes) ) def forward( self, tile_features: torch.Tensor # (N, embedding_dim) — предвычисленные ) -> tuple[torch.Tensor, torch.Tensor]: """ Возвращает (logits, attention_scores). attention_scores — для визуализации внимания на WSI. """ # Attention weights A = self.attention(tile_features) # (N, 1) A = torch.softmax(A, dim=0) # нормализация по тайлам # Взвешенная агрегация aggregated = (A * tile_features).sum(dim=0, keepdim=True) # (1, dim) logits = self.classifier(aggregated) return logits, A.squeeze() def _load_pathology_foundation(self, name: str) -> nn.Module: # Placeholder — реальная загрузка через Hugging Face Hub raise NotImplementedError( f'Load {name} from Hugging Face: ' f'MahmoodLab/{name}' ) 

Як візуалізація уваги допомагає патологу?

Heatmap уваги — ключовий інструмент інтерпретованості. Ми проектуємо attention scores назад на WSI, отримуючи кольорову карту, яка вказує на найбільш значущі ділянки. Патолог може звірити підозрілі області та прийняти рішення. Це знижує час аналізу на 40% і мінімізує суб'єктивність.

def create_attention_heatmap( slide: openslide.OpenSlide, tile_coords: list[tuple], # [(x, y), ...] в пикселях level-0 attention_scores: np.ndarray, # нормализованные attention weights tile_size: int, downsample: int = 32 # уменьшение для отображения ) -> np.ndarray: """ Проецируем attention scores обратно на WSI → heatmap. """ W, H = slide.dimensions heatmap = np.zeros((H // downsample, W // downsample), dtype=np.float32) for (x, y), score in zip(tile_coords, attention_scores): x_d = x // downsample y_d = y // downsample size_d = tile_size // downsample heatmap[y_d:y_d+size_d, x_d:x_d+size_d] = float(score) # Наложение на превью WSI thumbnail = np.array( slide.get_thumbnail((W // downsample, H // downsample)) ) heatmap_colored = cv2.applyColorMap( (heatmap * 255).astype(np.uint8), cv2.COLORMAP_JET ) overlay = cv2.addWeighted(thumbnail, 0.6, heatmap_colored, 0.4, 0) return overlay 
Попередньо навчені моделі UNI та CONCH детальніше UNI та CONCH — foundation моделі від MahmoodLab, навчені на >100 000 WSI з TCGA та інших джерел. Вони доступні через Hugging Face Hub за ліцензією, що вимагає прийняття умов. Використання таких енкодерів дає значний приріст точності порівняно з ResNet-50: у наших проєктах AUC піднімався з 0.91 до 0.97.

Етапи впровадження AI-системи

Впровадження проходить п'ять кроків:

  1. Аналіз даних — збір та ревізія ваших WSI-архівів, визначення форматів, перевірка якості сканів.
  2. Розмітка та підготовка — виділення референсних зрізів, створення тестової вибірки, аугментація.
  3. Навчання моделі — вибір архітектури (MIL, сегментація), fine-tuning pathology-pretrained енкодерів.
  4. Валідація та тестування — оцінка на відкладеній вибірці, побудова ROC-кривих, розрахунок метрик.
  5. Інтеграція та деплой — розгортання у вашій інфраструктурі, API для LIS, навчання персоналу.

Що входить у роботу

Компонент Опис
Тайлінг WSI Нарізка, фільтрація фону, багатомасштабне представлення
MIL-модель AttentionMIL з pathology-pretrained енкодером
Heatmap уваги Проекція attention scores, накладання на WSI
API для інтеграції REST/gRPC, підтримка DICOM, інтеграція з LIS
Навчання персоналу 2-денний воркшоп для патологів та IT-відділу
Гарантія якості AUC ≥ 0.95 на валідаційній вибірці, документація

Терміни та як замовити

Задача Термін
MIL-класифікатор на готових WSI 5–8 тижнів
Система з сегментацією тканин + клітинним аналізом 12–20 тижнів
Клінічно валідована система (CE IVD) 30–60 тижнів

Вартість розраховується індивідуально під ваш датасет та вимоги. Оцінимо проєкт протягом 3 робочих днів — просто зв'яжіться з нами. Ми працюємо більше 5 років у AI для медицини, виконали 20+ проєктів з цифрової патології. Надаємо гарантію на навчену модель та підтримку після впровадження.

Не відкладайте автоматизацію: патологи перевантажені, кожна хвилина на ручному аналізі — це ризик помилки. Зв'яжіться з нами, і ми покажемо, як AI може скоротити час діагностики на 40%. Замовте розробку AI-системи вже сьогодні — отримайте консультацію AI-інженера: ми допоможемо підібрати архітектуру під ваші завдання.