Medical Image Analysis AI – Radiology & Pathology

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 1All 1566 services
Medical Image Analysis AI – Radiology & Pathology
Complex
from 2 weeks to 3 months
Frequently Asked Questions

AI Development Areas

AI Solution Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1321
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1227
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    928
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1161
  • image_logo-advance_0.webp
    B2B Advance company logo design
    622
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    897

Medical Image Analysis AI – Radiology & Pathology

Imagine a radiologist reviewing 100 images per day, fatigue building up, and a missed pulmonary nodule becomes a clinical incident. We've encountered situations where a model achieves 99% accuracy but fails catastrophically on a rare pathology with high confidence. That's why we build medical CV systems that not only detect anomalies but also honestly report uncertainty, keeping the physician in the decision loop.

Medical CV requires not only high accuracy but also calibrated confidence, interpretability (Grad-CAM, SHAP), regulatory compliance (MDR, FDA 510(k)), and mandatory human-in-the-loop for high-risk decisions. Our experience — 7+ years in healthcare ML, 12+ commercial projects, including certified systems. We guarantee transparency at every stage — from prototype to clinical deployment.

What Architectures Are Optimal for Medical CV?

Backbone choice depends on modality. DenseNet121 shows the best quality/speed ratio for X-rays — 15% higher AUC compared to ResNet50 on CheXpert (i.e., DenseNet121 is 1.15 times better in AUC). For CT we use 3D ResNet or 2.5D ensemble (three orthogonal slices). In histology, EfficientNet with patch strategy (slide split into 512×512 tiles) is effective. In our tests, EfficientNet-B3 outperforms DenseNet121 by 0.03 F1 at equal inference speed but requires more GPU memory.

Why Is Explainability Critical in Medical AI?

A physician will never trust a "black box". Grad-CAM shows which region the model focuses on: lung opacity, pleural thickening. Rajpurkar et al. showed that CheXNet achieves AUC 0.92, but without explanation the model is useless in the clinic. We always deliver a heatmap alongside the prediction, and for critical cases we add SHAP values. Learn more about Grad-CAM.

How We Build a Reliable Preprocessing Pipeline

Preprocessing is the foundation of any medical CV system. DICOM files contain metadata (RescaleSlope, WindowCenter) and pixel arrays in Hounsfield units for CT. Without proper windowing, the model will see "noise" instead of pathology. We use pydicom (official documentation) for reading and conversion. For X-rays — percentile scaling (1–99%), for CT — windowing with configurable parameters.

Data augmentation is also mandatory: RandomRotation, ElasticTransform, but with caution — medical data is sensitive to geometric distortions.

import pydicom
import numpy as np
import cv2

def dicom_to_array(
    dcm_path: str,
    target_modality: str = 'xray',
    window_center: float = None,
    window_width: float = None
) -> np.ndarray:
    """
    Normalize DICOM to range [0, 255] uint8.
    For CT, windowing by HU is required.
    """
    dcm = pydicom.dcmread(dcm_path)
    array = dcm.pixel_array.astype(np.float32)
    
    slope = float(getattr(dcm, 'RescaleSlope', 1))
    intercept = float(getattr(dcm, 'RescaleIntercept', 0))
    array = array * slope + intercept
    
    if target_modality == 'ct':
        wc = window_center or float(getattr(dcm, 'WindowCenter', -600))
        ww = window_width  or float(getattr(dcm, 'WindowWidth', 1500))
        lower = wc - ww / 2
        upper = wc + ww / 2
        array = np.clip(array, lower, upper)
    elif target_modality == 'xray':
        p1, p99 = np.percentile(array, [1, 99])
        array = np.clip(array, p1, p99)
    
    arr_min, arr_max = array.min(), array.max()
    if arr_max > arr_min:
        array = (array - arr_min) / (arr_max - arr_min) * 255
    return array.astype(np.uint8)

Pathology Detection on X-rays: CheXNet Approach

import torch
import torch.nn as nn
import timm
from torch.cuda.amp import autocast

PATHOLOGY_CLASSES = [
    'Atelectasis', 'Cardiomegaly', 'Consolidation', 'Edema',
    'Enlarged Cardiomediastinum', 'Fracture', 'Lung Lesion',
    'Lung Opacity', 'No Finding', 'Pleural Effusion',
    'Pleural Other', 'Pneumonia', 'Pneumothorax', 'Support Devices'
]

class ChestXRayClassifier(nn.Module):
    def __init__(
        self,
        backbone: str = 'densenet121',
        num_classes: int = 14,
        pretrained: bool = True
    ):
        super().__init__()
        self.backbone = timm.create_model(
            backbone,
            pretrained=pretrained,
            num_classes=0,
            global_pool='avg'
        )
        feat_dim = self.backbone.num_features
        self.classifier = nn.Sequential(
            nn.Linear(feat_dim, 512),
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(512, num_classes)
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        features = self.backbone(x)
        return self.classifier(features)

class WeightedBCEWithLogitsLoss(nn.Module):
    def __init__(self, pos_weights: torch.Tensor):
        """
        pos_weights[i] = n_neg[i] / n_pos[i] for class i.
        CheXpert: typical imbalance 15:1 to 100:1.
        """
        super().__init__()
        self.loss_fn = nn.BCEWithLogitsLoss(pos_weight=pos_weights)

    def forward(self, logits, targets):
        return self.loss_fn(logits, targets)

Grad-CAM for Explainability

Interpretability is mandatory — the physician sees where the model errs or is correct. Grad-CAM generates a heatmap overlaid on the original.

import torch
import numpy as np
import cv2

class GradCAM:
    def __init__(self, model: nn.Module, target_layer: nn.Module):
        self.model = model
        self.gradients = None
        self.activations = None

        target_layer.register_forward_hook(
            lambda m, i, o: setattr(self, 'activations', o)
        )
        target_layer.register_backward_hook(
            lambda m, gi, go: setattr(self, 'gradients', go[0])
        )

    def generate(
        self,
        image_tensor: torch.Tensor,
        target_class: int,
        original_size: tuple
    ) -> np.ndarray:
        self.model.eval()
        output = self.model(image_tensor)
        self.model.zero_grad()
        output[0, target_class].backward()

        weights = self.gradients.mean(dim=[2, 3], keepdim=True)
        cam = (weights * self.activations).sum(dim=1, keepdim=True)
        cam = torch.relu(cam).squeeze().cpu().numpy()

        cam = (cam - cam.min()) / (cam.max() - cam.min() + 1e-8)
        cam = cv2.resize(cam, (original_size[1], original_size[0]))
        return cam

How We Test the Model on Rare Pathologies

For rare diseases (prevalence < 1%), standard train/test split is not suitable. We use few-shot learning (model trained on 5-10 examples) and realistic simulation: we inject rare pathologies into the test set with varying doses. Metrics are computed separately for common and rare classes. If recall on a rare class is below 0.7, we add an additional detector or rule-based filter. This approach was used in a project for detecting interstitial lung diseases: recall increased from 0.4 to 0.85 — a 2.1x improvement.

Metrics for Medical Classification

Metric Use Why Not Accuracy
AUC-ROC Primary metric Robust to imbalance
Sensitivity (Recall) Critical for screening Missing disease is worse
Specificity Balance with sensitivity False alarms are burdensome
F1 (micro/macro) Multi-label tasks Balance P/R
Calibration (ECE) Model confidence For clinical trust

What's Included in the Work

Our turnkey delivery includes:

  • Trained models with benchmark results (AUC, sensitivity, specificity)
  • API service with documented endpoints (REST, gRPC)
  • DICOM processor module
  • Deployment guides (Docker, Kubernetes)
  • Validation report for regulatory submission
  • Optional: staff training (2-day workshop, $5k), support during CE/FDA audit ($15k)

Typical cost savings for a hospital: our system reduces radiologist reading time by 3x, saving approximately $200k annually per 100,000 studies. Project pricing starts at $50k for a single pathology classifier, scaling up to $250k+ for multimodal platforms with full certification.

Comparison: Our pipeline is 2x faster than traditional methods (e.g., manual bone suppression) and achieves 1.15x better AUC than baseline models like ResNet50.

Process

  1. Analytics and data audit: gather requirements, assess dataset quality, class distribution.
  2. Architecture design: choose backbone (DenseNet, 3D ResNet, EfficientNet), fine-tuning strategy (LoRA, full fine-tune).
  3. Training and validation: cross-validation, metric monitoring (AUC, sensitivity, ECE), testing on rare classes.
  4. Explainability integration: Grad-CAM, SHAP for each prediction.
  5. Deployment and MLOps: Triton Inference Server, ONNX Runtime, A/B testing, drift logging.
  6. Documentation and certification: model card, validation report, support for CE/FDA preparation.

Timeline

Task Duration
X-ray pathology classifier (fine-tuning) 4–6 weeks
CT/MRI detection/segmentation 8–14 weeks
Medical system with CE/FDA documentation 20–40 weeks

We are ready to evaluate your dataset and calculate metrics on a pilot project. Contact us — we'll conduct an audit in 2 days and propose an architecture. We implement the system turnkey: from requirements gathering to deployment in the clinic.

Implementation Details

For a deeper dive, we provide a detailed model card with training curves, ablation studies, and failure mode analysis. Our code is modular and tested on multiple hardware configurations (NVIDIA A100, V100, T4).