AI for Retinal Imaging Analysis

We design and deploy artificial intelligence systems: from prototype to production-ready solutions. Our team combines expertise in machine learning, data engineering and MLOps to make AI work not in the lab, but in real business.
Showing 1 of 1 servicesAll 1566 services
AI for Retinal Imaging Analysis
Complex
~2-4 weeks
FAQ
AI Development Areas
AI Solution Development Stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823
  • image_logo-aider_0.jpg
    AIDER company logo development
    762
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    848

Разработка AI для анализа снимков глазного дна (Retinal Imaging)

Снимки глазного дна (fundus photography) — неинвазивный метод визуализации сетчатки. По состоянию сетчатки можно диагностировать: диабетическую ретинопатию (DR), глаукому, AMD (возрастную макулярную дегенерацию), гипертензивную ретинопатию. AI-анализ особенно ценен для массового скрининга в условиях дефицита офтальмологов.

Диабетическая ретинопатия: грейдирование

DR — ведущая причина слепоты у людей трудоспособного возраста. Грейдирование по шкале ICDR (0-4):

import torch
import timm
import torch.nn as nn
from torchvision import transforms

class DRGrader:
    DR_GRADES = {
        0: 'No DR',
        1: 'Mild NPDR',
        2: 'Moderate NPDR',
        3: 'Severe NPDR',
        4: 'Proliferative DR'
    }

    def __init__(self, model_path: str):
        # EfficientNet-B5 показывает лучший результат на Kaggle DR dataset
        backbone = timm.create_model('efficientnet_b5', pretrained=False)
        backbone.classifier = nn.Sequential(
            nn.Dropout(0.4),
            nn.Linear(backbone.classifier.in_features, 5)
        )
        backbone.load_state_dict(torch.load(model_path))
        backbone.eval()
        self.model = backbone

        self.transform = transforms.Compose([
            transforms.Resize((456, 456)),
            transforms.CenterCrop(400),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406],
                                  [0.229, 0.224, 0.225])
        ])

    @torch.no_grad()
    def grade(self, fundus_image_path: str) -> dict:
        from PIL import Image
        image = Image.open(fundus_image_path).convert('RGB')

        # Предобработка: CLAHE для улучшения контраста сосудов
        image = self._enhance_fundus(image)
        tensor = self.transform(image).unsqueeze(0)

        logits = self.model(tensor)
        probs = torch.softmax(logits, dim=1).squeeze().numpy()
        grade = int(probs.argmax())

        return {
            'grade': grade,
            'grade_label': self.DR_GRADES[grade],
            'probabilities': {self.DR_GRADES[i]: float(probs[i]) for i in range(5)},
            'referable': grade >= 2,  # направить к офтальмологу
            'vision_threatening': grade >= 3
        }

    def _enhance_fundus(self, image) -> 'PIL.Image':
        """CLAHE улучшение для сетчатки"""
        import cv2
        import numpy as np
        img_array = np.array(image)

        # Применяем CLAHE к L-каналу в LAB
        lab = cv2.cvtColor(img_array, cv2.COLOR_RGB2LAB)
        l, a, b = cv2.split(lab)
        clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
        l_enhanced = clahe.apply(l)
        enhanced = cv2.cvtColor(cv2.merge([l_enhanced, a, b]), cv2.COLOR_LAB2RGB)

        return Image.fromarray(enhanced)

Сегментация сосудов сетчатки

Сегментация сосудов важна для ранней диагностики изменений микроциркуляции:

import segmentation_models_pytorch as smp

# U-Net с SE-ResNeXt энкодером для сегментации сосудов
vessel_segmenter = smp.UnetPlusPlus(
    encoder_name='se_resnext50_32x4d',
    encoder_weights='imagenet',
    in_channels=3,
    classes=1,              # бинарная маска сосудов
    activation='sigmoid'
)

Метрика: AUC 0.9887 на DRIVE датасете (U-Net++, дообученный специфично).

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

from ultralytics import YOLO

class RetinalStructureDetector:
    def __init__(self, model_path: str):
        self.detector = YOLO(model_path)
        self.structures = ['optic_disc', 'macula', 'fovea']

    def detect(self, fundus_image: np.ndarray) -> dict:
        results = self.detector(fundus_image, conf=0.5)
        detected = {}

        for box in results[0].boxes:
            structure = self.structures[int(box.cls)]
            x1, y1, x2, y2 = map(int, box.xyxy[0])
            cx, cy = (x1+x2)//2, (y1+y2)//2

            detected[structure] = {
                'center': (cx, cy),
                'bbox': [x1, y1, x2, y2],
                'confidence': float(box.conf)
            }

        # C/D ratio (cup-to-disc ratio) для глаукомы
        if 'optic_disc' in detected:
            detected['cdr'] = self._calculate_cdr(fundus_image,
                                                    detected['optic_disc'])

        return detected

Скрининговые системы

AI-решение для массового скрининга ДР:

  • Mобильный сканер + AI → результат в 1 минуту
  • Без офтальмолога в контуре на первом этапе
  • Направление только тех, у кого grade ≥ 2 (referable DR)
  • 30–40% снижение нагрузки на офтальмологов

Примеры внедрений: IDx-DR (FDA-clearance), EyeArt (1,200+ клиник в США).

Публичные датасеты

Датасет Задача Изображений
Kaggle DR (EyePACS) Грейдирование DR 88,702
DRIVE Сегментация сосудов 40
STARE Сосуды + патологии 397
RIM-ONE Глаукома 455
MESSIDOR-2 DR грейдирование 1748
Задача AUC/Метрика Срок
DR grading EfficientNet-B5 AUC 0.96 6–10 недель
Сегментация сосудов AUC 0.99 6–8 недель
Полная ретинальная система 14–22 недели