Image-Based Anomaly Detection System

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
Image-Based Anomaly Detection System
Medium
~5 business days
FAQ
AI Development Areas
AI Solution Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1215
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • 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

System Development детекции аномалий по изображениям

Детекция аномалий на изображениях — задача нахождения отклонений от нормального состояния без явного определения класса дефекта. Ключевое отличие от supervised детекции: модель обучается только на нормальных примерах, не требуя размеченных дефектов. Applications: промышленный контроль качества, медицинская диагностика, безопасность.

PatchCore: лучший метод для промышленных задач

from anomalib.models import PatchCore
from anomalib.data import Folder
from anomalib import TaskType
from lightning.pytorch import Trainer

# Датасет: только нормальные изображения в папке train/good/
datamodule = Folder(
    name='my_product',
    root='./dataset',
    normal_dir='train/good',
    abnormal_dir='test/defective',  # только для валидации
    task=TaskType.SEGMENTATION,
    image_size=(256, 256),
    train_batch_size=32,
    eval_batch_size=32
)

model = PatchCore(
    backbone='wide_resnet50_2',
    pre_trained=True,
    layers=['layer2', 'layer3'],  # какие слои ResNet использовать
    coreset_sampling_ratio=0.1,    # 10% от memory bank
    num_neighbors=9
)

trainer = Trainer(max_epochs=1)  # PatchCore не обучается градиентно
trainer.fit(model, datamodule)

Сравнение методов Anomaly Detection

Метод AUROC MVTec-AD Скорость Особенность
PatchCore 99.1% Средняя Memory bank
SimpleNet 98.7% Быстрая Простой
WinCLIP 91.8% Медленная Zero-shot
STFPM 97.9% Быстрая Teacher-Student
FastFlow 97.5% Очень быстрая Normalizing Flow
EfficientAD 98.9% Очень быстрая Рекомендуется для prod

EfficientAD — лучший выбор для production из-за скорости инференса при сохранении высокого AUROC.

Настройка порога обнаружения

class AnomalyDetector:
    def __init__(self, model_path: str, threshold: float = None):
        self.model = load_model(model_path)
        self.threshold = threshold or self._calibrate_threshold()

    def _calibrate_threshold(self, fp_rate: float = 0.01) -> float:
        """Порог при заданном False Positive Rate"""
        # Прогоняем нормальные изображения из валидационного набора
        val_scores = self._predict_normal_samples()
        # Порог на уровне (1 - fp_rate) квантиля
        threshold = np.quantile(val_scores, 1 - fp_rate)
        return float(threshold)

    def predict(self, image: np.ndarray) -> dict:
        result = self.model(image)
        score = float(result.anomaly_score)

        return {
            'anomaly_score': score,
            'is_anomaly': score > self.threshold,
            'severity': self._classify_severity(score),
            'heatmap': result.anomaly_map,
            'threshold': self.threshold
        }

    def _classify_severity(self, score: float) -> str:
        if score < self.threshold:
            return 'normal'
        elif score < self.threshold * 1.5:
            return 'minor'
        elif score < self.threshold * 2.5:
            return 'moderate'
        return 'severe'

Локализация аномалий

Тепловая карта (anomaly map) позволяет локализовать дефект на изображении:

import matplotlib.pyplot as plt
import matplotlib.cm as cm

def visualize_anomaly(original: np.ndarray,
                       anomaly_map: np.ndarray,
                       threshold: float) -> np.ndarray:
    # Нормализация тепловой карты
    heatmap_norm = (anomaly_map - anomaly_map.min()) / \
                   (anomaly_map.max() - anomaly_map.min() + 1e-8)

    # Colormap overlay
    heatmap_colored = cv2.applyColorMap(
        (heatmap_norm * 255).astype(np.uint8),
        cv2.COLORMAP_JET
    )

    # Маска аномальных регионов
    _, mask = cv2.threshold(
        (heatmap_norm * 255).astype(np.uint8),
        int(threshold * 255), 255, cv2.THRESH_BINARY
    )
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL,
                                    cv2.CHAIN_APPROX_SIMPLE)

    # Overlay на оригинал
    overlay = cv2.addWeighted(original, 0.6, heatmap_colored, 0.4, 0)
    cv2.drawContours(overlay, contours, -1, (0, 255, 0), 2)

    return overlay

Работа с новыми категориями продуктов

При добавлении нового продукта: собираем 50–200 нормальных изображений → инициализация нового PatchCore за 5–10 минут без GPU. Нет необходимости в переобучении с нуля.

Сценарий Срок
1 продукт, PatchCore из коробки 1–2 недели
5–10 продуктов, калибровка порогов 3–5 недель
Промышленная система с онлайн-обучением 6–10 недель