Разработка системы определения эмоций по лицу (Facial Emotion Recognition)

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
Разработка системы определения эмоций по лицу (Facial Emotion Recognition)
Средняя
от 1 недели до 3 месяцев
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1240
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1167
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    867
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1084
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    563
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    829

Разработка системы определения эмоций по лицу (Facial Emotion Recognition)

Распознавание эмоций по мимике — задача классификации выражения лица на базовые состояния. Классическая модель Экмана выделяет 7 универсальных эмоций: радость, грусть, гнев, страх, удивление, отвращение, нейтральное. Применения: анализ вовлечённости в онлайн-обучении, мониторинг удовлетворённости клиентов в колл-центре, исследования UX, контроль состояния водителя.

Архитектура модели

Пайплайн: детекция лица → выравнивание → классификация эмоций.

import torch
import torch.nn as nn
import timm
import cv2
import numpy as np
from insightface.app import FaceAnalysis

class EmotionRecognizer:
    def __init__(self, model_path: str):
        # Детекция и выравнивание лица
        self.detector = FaceAnalysis(allowed_modules=['detection'])
        self.detector.prepare(ctx_id=0, det_size=(640, 640))

        # Классификатор эмоций
        backbone = timm.create_model('efficientnet_b0', pretrained=False)
        backbone.classifier = nn.Sequential(
            nn.Dropout(0.3),
            nn.Linear(backbone.num_features, 7)
        )
        backbone.load_state_dict(torch.load(model_path))
        backbone.eval()
        self.model = backbone

        self.emotions = ['angry', 'disgust', 'fear', 'happy',
                         'neutral', 'sad', 'surprise']
        self.transform = get_inference_transform()

    @torch.no_grad()
    def predict(self, image: np.ndarray) -> list[dict]:
        faces = self.detector.get(image)
        results = []

        for face in faces:
            x1, y1, x2, y2 = face.bbox.astype(int)
            face_crop = image[y1:y2, x1:x2]
            face_crop = cv2.resize(face_crop, (48, 48))

            tensor = self.transform(face_crop).unsqueeze(0)
            logits = self.model(tensor)
            probs = torch.softmax(logits, dim=1).squeeze()

            emotion_scores = {
                self.emotions[i]: float(probs[i])
                for i in range(7)
            }
            dominant = max(emotion_scores, key=emotion_scores.get)

            results.append({
                'bbox': [x1, y1, x2, y2],
                'emotion': dominant,
                'confidence': emotion_scores[dominant],
                'all_scores': emotion_scores
            })

        return results

Датасеты и качество моделей

Датасет Размер Условия Классы
FER-2013 35k фото Дикая природа 7
AffectNet 1M фото Дикая природа 8 (+ contempt)
RAF-DB 30k фото Реальные 7 + compound
CK+ 593 видео Лабораторные 7
SFEW 1766 кадров Кинофильмы 7

Точность на FER-2013:

  • EfficientNet-B0 fine-tuned: 73.1%
  • Vision Transformer (ViT-B/16): 74.8%
  • EfficientFace: 73.3%

Главная сложность: метки в публичных датасетах субъективны, люди не соглашаются в 30–40% случаев. Accuracy 75% — это предел для FER-2013 из-за человеческого несогласия.

Временная аналитика на видео

Покадровая классификация нестабильна — эмоция «мигает» между кадрами. Решения:

  • Temporal smoothing: скользящее среднее по 10–30 кадрам
  • RNN/LSTM поверх frame-level классификатора: учитывает временную динамику
  • Aggregation по интервалу: средняя эмоция за N-секундный интервал для аналитики
from collections import deque

class TemporalEmotionTracker:
    def __init__(self, window_size: int = 30):
        self.window = deque(maxlen=window_size)

    def update(self, emotion_scores: dict) -> dict:
        self.window.append(emotion_scores)
        # Усредняем по окну
        averaged = {}
        for emotion in emotion_scores:
            averaged[emotion] = sum(
                frame[emotion] for frame in self.window
            ) / len(self.window)
        return averaged

Ограничения и этические аспекты

Важно понимать ограничения технологии:

  • Культурные различия в выражении эмоций (мимика варьируется между культурами)
  • Нейтральное лицо ≠ нейтральное состояние человека
  • Актёрская мимика отличается от искренней

Технология не должна использоваться для скрытого мониторинга сотрудников без их ведома. В production всегда требуется юридическое согласие.

Задача Срок
SDK для мобильного/веб приложения 2–3 недели
Аналитика вовлечённости на видео 3–5 недель
Кастомная модель на корпоративном датасете 5–8 недель