Проблемы распознавания эмоций в современных условиях
Защита через месяц, а работа не готова?
Наши эксперты выполнят ВКР по распознаванию эмоций всего за 14 дней! Напишите в Telegram прямо сейчас и получите бесплатную консультацию по выбору архитектуры системы.
Современные системы взаимодействия человека и компьютера все чаще требуют понимания эмоционального состояния пользователя для повышения качества взаимодействия. Согласно исследованию MIT Technology Review (2024), системы, способные распознавать эмоции, повышают удовлетворенность пользователей на 35-40% и эффективность взаимодействия на 25-30%. Однако точное распознавание эмоций остается сложной задачей из-за их субъективности, культурных различий и многообразия проявлений. Традиционные подходы, основанные только на анализе изображений или аудио, часто не учитывают контекст и семантику, что приводит к ошибкам в распознавании.
Актуальность реализации распознавания эмоций на основе нейронных сетей и логико-семантических технологий обусловлена растущей потребностью в более точных и контекстно-зависимых системах распознавания эмоций. Это особенно важно для студентов ФИТ НГУ, изучающих прикладную информатику и методы искусственного интеллекта, так как позволяет применить теоретические знания на практике и получить навыки работы с современными технологиями компьютерного зрения, обработки естественного языка и логического вывода.
В данной статье мы подробно рассмотрим современные подходы к распознаванию эмоций с использованием нейронных сетей и логико-семантических технологий. Вы узнаете о ключевых архитектурных решениях, практических методах реализации и рекомендациях по созданию эффективных систем. Мы также разберем типичные ошибки, которые допускают студенты при работе с этой сложной темой, и предложим проверенные решения для успешного выполнения ВКР.
Эта тема особенно важна для студентов ФИТ НГУ, так как требует комплексного применения знаний в области машинного обучения, компьютерного зрения и логических систем. Успешная реализация подобного проекта не только поможет в написании качественной выпускной квалификационной работы, но и станет ценным навыком для будущей профессиональной деятельности в области разработки систем искусственного интеллекта и анализа поведения.
Если вы испытываете трудности с пониманием архитектуры нейронных сетей или реализацией конкретных компонентов системы распознавания эмоций, рекомендуем ознакомиться с нашими гарантиями и отзывами клиентов, которые подтверждают высокое качество наших услуг.
Дополнительный список тем для ВКР ФИТ НГУ на 2025-2026 учебный год можно найти здесь.
Срочная помощь по вашей теме: Получите консультацию за 10 минут! Telegram: @Diplomit Телефон/WhatsApp: +7 (987) 915-99-32, Email: admin@diplom-it.ru
Оформите заказ онлайн: Заказать ВКР ФИТ НГУ
Основы распознавания эмоций
Ключевые проблемы распознавания эмоций
| Проблема | Описание | Требования к решению |
|---|---|---|
| Субъективность эмоций | Эмоции субъективны и могут по-разному проявляться у разных людей | Индивидуальная адаптация, учет личных особенностей пользователя |
| Культурные различия | Выражение эмоций варьируется в зависимости от культуры | Многоязычная и межкультурная поддержка, адаптация к культурным нормам |
| Контекстная зависимость | Одно и то же выражение может означать разные эмоции в разных контекстах | Интеграция контекстной информации, логико-семантический анализ |
| Много модальностей | Эмоции проявляются через лицо, голос, язык тела, текст | Мультимодальный анализ, интеграция данных из разных источников |
| Этические вопросы | Проблемы приватности и этичности распознавания эмоций | Системы согласия, анонимизация данных, прозрачность алгоритмов |
Технические основы распознавания эмоций
Реализация распознавания эмоций на основе нейронных сетей и логико-семантических технологий основывается на ряде ключевых концепций:
Основы распознавания эмоций
- Компьютерное зрение — методы анализа изображений и видео для распознавания выражений лица
- Обработка речи — анализ аудиосигнала для определения эмоциональной окраски речи
- Обработка естественного языка — анализ текста для определения эмоциональной окраски
- Мультимодальный анализ — интеграция данных из разных источников для повышения точности
- Логико-семантические системы — использование логических правил и семантических моделей для интерпретации данных
- Глубокое обучение — применение нейронных сетей для распознавания сложных паттернов
Эти концепции лежат в основе современных систем распознавания эмоций и должны быть хорошо поняты при разработке таких систем.
Современные подходы к распознаванию эмоций
В последние годы в области распознавания эмоций наблюдается несколько ключевых тенденций:
| Подход | Описание | Примеры применения |
|---|---|---|
| Мультимодальный анализ | Интеграция данных из разных источников (лицо, голос, текст, жесты) | Системы анализа клиентского опыта, виртуальные собеседования, образовательные платформы |
| Контекстно-зависимый анализ | Учет контекста взаимодействия для интерпретации эмоций | Анализ встреч, мониторинг психоэмоционального состояния, персонализированные рекомендации |
| Логико-семантические модели | Использование логических правил и семантических моделей для интерпретации | Системы принятия решений, анализ социальных взаимодействий, диагностика эмоциональных расстройств |
| Персонализированный анализ | Адаптация системы к индивидуальным особенностям пользователя | Персональные ассистенты, системы мониторинга здоровья, образовательные платформы |
| Реальный-time анализ | Анализ эмоций в реальном времени с минимальной задержкой | Интерактивные системы, геймификация, виртуальная реальность |
Архитектура и реализация системы распознавания эмоций
Выбор архитектурного подхода
Для эффективной реализации системы распознавания эмоций на основе нейронных сетей и логико-семантических технологий рекомендуется использовать следующую архитектуру:
Архитектура системы распознавания эмоций
- Слой сбора данных — получение данных из различных источников (камера, микрофон, текстовый ввод)
- Слой предварительной обработки — очистка, нормализация и подготовка данных
- Слой модального анализа — распознавание эмоций в каждом модальном канале
- Слой интеграции модальностей — объединение результатов из разных источников
- Слой логико-семантического анализа — интерпретация результатов с учетом контекста
- Слой принятия решений — формирование выводов и рекомендаций на основе анализа
- Слой обратной связи — сбор данных для улучшения системы
Эта многоуровневая архитектура обеспечивает гибкость и возможность расширения функциональности без переработки всей системы.
Пример реализации системы распознавания эмоций на Python
Рассмотрим пример реализации ключевых компонентов системы распознавания эмоций:
# emotion_recognition.py
# Реализация системы распознавания эмоций на основе нейронных сетей и логико-семантических технологий
import cv2
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from transformers import pipeline, AutoModelForSequenceClassification, AutoTokenizer
import logging
from typing import Dict, List, Tuple, Optional, Any
import json
from sklearn.metrics.pairwise import cosine_similarity
import re
# Настройка логирования
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class FaceEmotionAnalyzer:
"""Анализ эмоций по изображению лица"""
def __init__(self, model_path: str = "fer2013_resnet50.pth"):
self.model = self._load_model(model_path)
self.emotion_labels = ['angry', 'disgust', 'fear', 'happy', 'sad', 'surprise', 'neutral']
def _load_model(self, model_path: str):
"""Загрузка предобученной модели для распознавания эмоций по лицу"""
# В реальной системе здесь будет загрузка модели
# Для примера создаем заглушку
class MockModel(nn.Module):
def __init__(self):
super().__init__()
def forward(self, x):
# Генерируем случайные вероятности для демонстрации
batch_size = x.shape[0]
return torch.rand(batch_size, 7)
return MockModel()
def detect_faces(self, frame: np.ndarray) -> List[Tuple[int, int, int, int]]:
"""Обнаружение лиц на изображении"""
# Используем каскад Хаара для обнаружения лиц
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
return faces
def preprocess_face(self, face_img: np.ndarray, size: tuple = (48, 48)) -> torch.Tensor:
"""Предварительная обработка изображения лица"""
# Конвертация в оттенки серого
if len(face_img.shape) == 3:
face_img = cv2.cvtColor(face_img, cv2.COLOR_BGR2GRAY)
# Изменение размера
face_img = cv2.resize(face_img, size)
# Нормализация
face_img = face_img / 255.0
# Добавление размерностей для батча и каналов
face_img = np.expand_dims(face_img, axis=0)
face_img = np.expand_dims(face_img, axis=0)
# Конвертация в тензор
return torch.tensor(face_img, dtype=torch.float32)
def analyze_frame(self, frame: np.ndarray) -> List[Dict]:
"""
Анализ кадра на наличие эмоций
Args:
frame: Кадр видео в формате numpy array
Returns:
Список обнаруженных эмоций с координатами лиц и вероятностями
"""
faces = self.detect_faces(frame)
results = []
for (x, y, w, h) in faces:
# Извлечение области лица
face_img = frame[y:y+h, x:x+w]
# Предварительная обработка
processed_face = self.preprocess_face(face_img)
# Предсказание эмоции
with torch.no_grad():
outputs = self.model(processed_face)
probabilities = F.softmax(outputs, dim=1)[0]
# Формирование результата
emotion_probs = {self.emotion_labels[i]: float(probabilities[i]) for i in range(len(self.emotion_labels))}
dominant_emotion = max(emotion_probs, key=emotion_probs.get)
results.append({
"bbox": (int(x), int(y), int(w), int(h)),
"dominant_emotion": dominant_emotion,
"emotion_probs": emotion_probs,
"confidence": float(emotion_probs[dominant_emotion])
})
return results
class SpeechEmotionAnalyzer:
"""Анализ эмоций по речи"""
def __init__(self, model_name: str = "jungjin5/emotion_recognition_wav2vec2"):
# В реальной системе здесь будет загрузка модели
# Для примера создаем заглушку
self.emotion_labels = ['neutral', 'calm', 'happy', 'sad', 'angry', 'fearful', 'disgust', 'surprised']
logger.info(f"Speech emotion analyzer initialized with model {model_name}")
def analyze_audio(self, audio_path: str) -> Dict:
"""
Анализ аудио на наличие эмоций
Args:
audio_path: Путь к аудиофайлу
Returns:
Словарь с результатами анализа
"""
# В реальной системе здесь будет обработка аудио
# Для примера генерируем случайные результаты
# Имитация анализа аудио
emotion_probs = {emotion: np.random.random() for emotion in self.emotion_labels}
total = sum(emotion_probs.values())
emotion_probs = {k: v/total for k, v in emotion_probs.items()}
dominant_emotion = max(emotion_probs, key=emotion_probs.get)
return {
"dominant_emotion": dominant_emotion,
"emotion_probs": emotion_probs,
"confidence": emotion_probs[dominant_emotion]
}
class TextEmotionAnalyzer:
"""Анализ эмоций по тексту"""
def __init__(self, model_name: str = "j-hartmann/emotion-english-distilroberta-base"):
self.tokenizer = AutoTokenizer.from_pretrained(model_name)
self.model = AutoModelForSequenceClassification.from_pretrained(model_name)
self.emotion_labels = ['anger', 'disgust', 'fear', 'joy', 'neutral', 'sadness', 'surprise']
def analyze_text(self, text: str) -> Dict:
"""
Анализ текста на наличие эмоций
Args:
text: Текст для анализа
Returns:
Словарь с результатами анализа
"""
# Токенизация
inputs = self.tokenizer(text, return_tensors="pt", truncation=True, max_length=512, padding=True)
# Предсказание
with torch.no_grad():
outputs = self.model(**inputs)
probabilities = F.softmax(outputs.logits, dim=1)[0]
# Формирование результата
emotion_probs = {self.emotion_labels[i]: float(probabilities[i]) for i in range(len(self.emotion_labels))}
dominant_emotion = max(emotion_probs, key=emotion_probs.get)
return {
"dominant_emotion": dominant_emotion,
"emotion_probs": emotion_probs,
"confidence": float(emotion_probs[dominant_emotion])
}
class MultimodalFusion:
"""Интеграция результатов из разных модальностей"""
def __init__(self, weights: Dict[str, float] = None):
# Веса для разных модальностей
self.weights = weights or {
"face": 0.4,
"speech": 0.3,
"text": 0.3
}
# Проверка, что сумма весов равна 1
total_weight = sum(self.weights.values())
if not np.isclose(total_weight, 1.0):
# Нормализация весов
self.weights = {k: v/total_weight for k, v in self.weights.items()}
def fuse_emotions(self, face_results: List[Dict], speech_result: Dict, text_result: Dict) -> Dict:
"""
Объединение результатов из разных модальностей
Args:
face_results: Результаты анализа лица (может быть несколько лиц)
speech_result: Результаты анализа речи
text_result: Результаты анализа текста
Returns:
Объединенные результаты анализа
"""
# Для простоты предполагаем, что анализируем одно лицо
if not face_results:
face_emotion_probs = {emotion: 0.0 for emotion in self._get_all_emotions()}
else:
# Берем первое лицо для примера
face_emotion_probs = face_results[0]["emotion_probs"]
# Приведение к общему набору эмоций
face_probs = self._normalize_emotions(face_emotion_probs, "face")
speech_probs = self._normalize_emotions(speech_result["emotion_probs"], "speech")
text_probs = self._normalize_emotions(text_result["emotion_probs"], "text")
# Объединение вероятностей
fused_probs = {}
all_emotions = set(face_probs.keys()) | set(speech_probs.keys()) | set(text_probs.keys())
for emotion in all_emotions:
weighted_sum = (
self.weights["face"] * face_probs.get(emotion, 0.0) +
self.weights["speech"] * speech_probs.get(emotion, 0.0) +
self.weights["text"] * text_probs.get(emotion, 0.0)
)
fused_probs[emotion] = weighted_sum
# Нормализация
total = sum(fused_probs.values())
if total > 0:
fused_probs = {k: v/total for k, v in fused_probs.items()}
# Определение доминирующей эмоции
dominant_emotion = max(fused_probs, key=fused_probs.get)
return {
"dominant_emotion": dominant_emotion,
"fused_emotion_probs": fused_probs,
"face_probs": face_probs,
"speech_probs": speech_probs,
"text_probs": text_probs,
"confidence": fused_probs[dominant_emotion]
}
def _get_all_emotions(self) -> List[str]:
"""Получение общего набора эмоций"""
return ['anger', 'disgust', 'fear', 'happy', 'sad', 'surprise', 'neutral']
def _normalize_emotions(self, probs: Dict[str, float], modality: str) -> Dict[str, float]:
"""Нормализация вероятностей эмоций к общему набору"""
normalized = {}
common_emotions = self._get_all_emotions()
# Сопоставление эмоций разных модальностей
mapping = {
"face": {
"angry": "anger",
"disgust": "disgust",
"fear": "fear",
"happy": "happy",
"sad": "sad",
"surprise": "surprise",
"neutral": "neutral"
},
"speech": {
"angry": "anger",
"disgust": "disgust",
"fearful": "fear",
"happy": "happy",
"sad": "sad",
"surprised": "surprise",
"neutral": "neutral"
},
"text": {
"anger": "anger",
"disgust": "disgust",
"fear": "fear",
"joy": "happy",
"sadness": "sad",
"surprise": "surprise",
"neutral": "neutral"
}
}
for src_emotion, prob in probs.items():
# Пытаемся найти соответствие в общем наборе
target_emotion = mapping[modality].get(src_emotion, None)
if target_emotion and target_emotion in common_emotions:
normalized[target_emotion] = normalized.get(target_emotion, 0.0) + prob
# Нормализация полученных вероятностей
total = sum(normalized.values())
if total > 0:
normalized = {k: v/total for k, v in normalized.items()}
# Добавляем отсутствующие эмоции с нулевой вероятностью
for emotion in common_emotions:
if emotion not in normalized:
normalized[emotion] = 0.0
return normalized
class SemanticEmotionInterpreter:
"""Логико-семантическая интерпретация эмоций"""
def __init__(self, knowledge_base_path: str = "emotion_knowledge_base.json"):
self.knowledge_base = self._load_knowledge_base(knowledge_base_path)
def _load_knowledge_base(self, path: str) -> Dict:
"""Загрузка базы знаний для семантической интерпретации"""
# В реальной системе здесь будет загрузка из файла
# Для примера создаем базу знаний в коде
return {
"context_rules": [
{
"condition": "topic == 'bad_news'",
"effects": {"sad": 0.3, "fear": 0.2}
},
{
"condition": "topic == 'good_news'",
"effects": {"happy": 0.4, "surprise": 0.1}
},
{
"condition": "interruption_count > 3",
"effects": {"anger": 0.3, "frustration": 0.2}
}
],
"cultural_rules": {
"western": {
"smiling": {"happy": 0.7, "polite": 0.3},
"eye_contact": {"confidence": 0.6, "aggression": 0.1}
},
"eastern": {
"smiling": {"polite": 0.6, "happy": 0.4},
"eye_contact": {"respect": 0.5, "disrespect": 0.2}
}
},
"temporal_patterns": [
{
"pattern": "happy -> sad",
"interpretation": "disappointment",
"weight": 0.7
},
{
"pattern": "neutral -> angry",
"interpretation": "sudden frustration",
"weight": 0.8
}
]
}
def interpret_emotions(self,
fused_emotion: Dict,
context: Dict = None,
cultural_background: str = "western") -> Dict:
"""
Семантическая интерпретация эмоций с учетом контекста
Args:
fused_emotion: Объединенные результаты анализа эмоций
context: Контекстная информация
cultural_background: Культурный контекст
Returns:
Интерпретированные результаты с учетом контекста
"""
context = context or {}
result = {
"base_emotions": fused_emotion["fused_emotion_probs"],
"interpreted_emotions": dict(fused_emotion["fused_emotion_probs"]),
"explanations": [],
"context_influences": []
}
# 1. Применение контекстных правил
for rule in self.knowledge_base["context_rules"]:
try:
# Оценка условия правила
if self._evaluate_condition(rule["condition"], context):
# Применение эффектов
for emotion, effect in rule["effects"].items():
if emotion in result["interpreted_emotions"]:
result["interpreted_emotions"][emotion] = min(1.0, result["interpreted_emotions"][emotion] + effect)
result["context_influences"].append(f"Контекст '{rule['condition']}' увеличил вероятность '{emotion}' на {effect}")
except Exception as e:
logger.error(f"Ошибка при применении контекстного правила: {str(e)}")
# 2. Применение культурных правил
cultural_rules = self.knowledge_base["cultural_rules"].get(cultural_background, {})
if "smiling" in context and cultural_rules.get("smiling"):
for emotion, weight in cultural_rules["smiling"].items():
if emotion in result["interpreted_emotions"]:
# Адаптация интерпретации улыбки в зависимости от культуры
smiling_intensity = context.get("smiling_intensity", 0.5)
adjustment = weight * smiling_intensity
result["interpreted_emotions"][emotion] = min(1.0, result["interpreted_emotions"][emotion] + adjustment)
result["context_influences"].append(f"Культурный контекст скорректировал интерпретацию улыбки для '{emotion}' на {adjustment}")
# 3. Нормализация после корректировок
total = sum(result["interpreted_emotions"].values())
if total > 0:
result["interpreted_emotions"] = {k: v/total for k, v in result["interpreted_emotions"].items()}
# 4. Определение доминирующей интерпретированной эмоции
dominant_emotion = max(result["interpreted_emotions"], key=result["interpreted_emotions"].get)
result["interpreted_dominant_emotion"] = dominant_emotion
result["interpreted_confidence"] = result["interpreted_emotions"][dominant_emotion]
return result
def _evaluate_condition(self, condition: str, context: Dict) -> bool:
"""Оценка условия контекстного правила"""
# Упрощенная реализация для примера
# В реальной системе нужно использовать безопасный парсер выражений
try:
# Замена операторов для безопасного выполнения
safe_condition = condition.replace("==", " == ").replace(">", " > ").replace("<", " < ")
# Разбор условия
parts = safe_condition.split()
if len(parts) == 3:
var, op, val = parts
if var in context:
# Преобразование значения контекста
ctx_val = context[var]
# Преобразование значения условия
if val.replace('.', '').isdigit():
val = float(val) if '.' in val else int(val)
elif val in ["True", "False"]:
val = val == "True"
# Оценка условия
if op == "==":
return ctx_val == val
elif op == ">":
return ctx_val > val
elif op == "<":
return ctx_val < val
return False
except Exception as e:
logger.error(f"Ошибка при оценке условия '{condition}': {str(e)}")
return False
class EmotionRecognitionSystem:
"""Основная система распознавания эмоций"""
def __init__(self,
face_model_path: str = "fer2013_resnet50.pth",
text_model_name: str = "j-hartmann/emotion-english-distilroberta-base",
cultural_background: str = "western"):
self.face_analyzer = FaceEmotionAnalyzer(face_model_path)
self.speech_analyzer = SpeechEmotionAnalyzer()
self.text_analyzer = TextEmotionAnalyzer(text_model_name)
self.multimodal_fusion = MultimodalFusion()
self.semantic_interpreter = SemanticEmotionInterpreter()
self.cultural_background = cultural_background
def analyze_interaction(self,
video_frame: np.ndarray = None,
audio_path: str = None,
text_input: str = None,
context: Dict = None) -> Dict:
"""
Анализ взаимодействия на основе различных модальностей
Args:
video_frame: Кадр видео
audio_path: Путь к аудиофайлу
text_input: Текстовый ввод
context: Контекстная информация
Returns:
Результаты анализа
"""
result = {
"timestamp": str(datetime.now()),
"raw_analysis": {},
"fused_analysis": None,
"interpreted_analysis": None,
"status": "success"
}
try:
# Анализ по лицу
if video_frame is not None:
face_results = self.face_analyzer.analyze_frame(video_frame)
result["raw_analysis"]["face"] = face_results
else:
result["raw_analysis"]["face"] = []
# Анализ по речи
if audio_path is not None:
speech_result = self.speech_analyzer.analyze_audio(audio_path)
result["raw_analysis"]["speech"] = speech_result
else:
result["raw_analysis"]["speech"] = {
"dominant_emotion": "neutral",
"emotion_probs": {e: 0.0 for e in self.speech_analyzer.emotion_labels},
"confidence": 0.0
}
# Анализ по тексту
if text_input and text_input.strip():
text_result = self.text_analyzer.analyze_text(text_input)
result["raw_analysis"]["text"] = text_result
else:
result["raw_analysis"]["text"] = {
"dominant_emotion": "neutral",
"emotion_probs": {e: 0.0 for e in self.text_analyzer.emotion_labels},
"confidence": 0.0
}
# Объединение результатов
fused_result = self.multimodal_fusion.fuse_emotions(
result["raw_analysis"]["face"],
result["raw_analysis"]["speech"],
result["raw_analysis"]["text"]
)
result["fused_analysis"] = fused_result
# Семантическая интерпретация
interpreted_result = self.semantic_interpreter.interpret_emotions(
fused_result,
context,
self.cultural_background
)
result["interpreted_analysis"] = interpreted_result
except Exception as e:
logger.error(f"Ошибка анализа взаимодействия: {str(e)}")
result["status"] = "error"
result["error"] = str(e)
return result
def process_video_stream(self, video_source: int = 0, callback=None):
"""
Обработка видеопотока в реальном времени
Args:
video_source: Источник видео (0 - веб-камера)
callback: Функция обратного вызова для обработки результатов
"""
cap = cv2.VideoCapture(video_source)
try:
while True:
ret, frame = cap.read()
if not ret:
break
# Анализ кадра
result = self.analyze_interaction(
video_frame=frame,
context={"current_topic": "general_conversation"}
)
# Отображение результатов на кадре
if result["status"] == "success" and result["raw_analysis"]["face"]:
for face in result["raw_analysis"]["face"]:
x, y, w, h = face["bbox"]
cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
# Отображение доминирующей эмоции
emotion = face["dominant_emotion"]
confidence = face["confidence"]
cv2.putText(frame, f"{emotion} ({confidence:.2f})",
(x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)
# Отображение кадра
cv2.imshow('Emotion Recognition', frame)
# Вызов callback-функции, если предоставлена
if callback:
callback(result)
# Выход по нажатию 'q'
if cv2.waitKey(1) & 0xFF == ord('q'):
break
finally:
cap.release()
cv2.destroyAllWindows()
# Пример использования
if __name__ == "__main__":
# Инициализация системы распознавания эмоций
emotion_system = EmotionRecognitionSystem()
# Пример анализа текста
text_input = "Я очень рад, что мы наконец-то встретились! Это действительно замечательный день."
text_result = emotion_system.text_analyzer.analyze_text(text_input)
print("Анализ текста:")
print(f"Доминирующая эмоция: {text_result['dominant_emotion']}")
print(f"Вероятности: {text_result['emotion_probs']}")
# Пример анализа взаимодействия (в реальной системе здесь будут реальные данные)
context = {
"current_topic": "good_news",
"smiling": True,
"smiling_intensity": 0.8
}
# В реальной системе здесь будут реальные данные с камеры и микрофона
video_frame = np.zeros((480, 640, 3), dtype=np.uint8) # Заглушка для кадра
audio_path = "sample_audio.wav" # Заглушка для аудио
interaction_result = emotion_system.analyze_interaction(
video_frame=video_frame,
audio_path=audio_path,
text_input=text_input,
context=context
)
print("\nРезультаты анализа взаимодействия:")
print(f"Объединенная доминирующая эмоция: {interaction_result['fused_analysis']['dominant_emotion']}")
print(f"Интерпретированная эмоция: {interaction_result['interpreted_analysis']['interpreted_dominant_emotion']}")
print(f"Пояснения: {interaction_result['interpreted_analysis']['explanations']}")
// src/services/emotionService.js
// Сервис для взаимодействия с системой распознавания эмоций
import axios from 'axios';
class EmotionService {
constructor() {
this.apiUrl = process.env.REACT_APP_EMOTION_API_URL || 'http://localhost:5000/api/v1/emotion';
this.headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.REACT_APP_EMOTION_API_KEY || ''}`
};
}
/**
* Анализ эмоций по тексту
*/
async analyzeText(text) {
try {
const response = await axios.post(`${this.apiUrl}/text`, {
text
}, {
headers: this.headers
});
return {
success: true,
result: response.data
};
} catch (error) {
console.error('Text emotion analysis error:', error);
return {
success: false,
error: error.response?.data?.error || 'Произошла ошибка при анализе текста'
};
}
}
/**
* Анализ эмоций по аудио
*/
async analyzeAudio(audioBlob) {
try {
const formData = new FormData();
formData.append('audio', audioBlob, 'recording.wav');
const response = await axios.post(`${this.apiUrl}/audio`, formData, {
headers: {
...this.headers,
'Content-Type': 'multipart/form-data'
}
});
return {
success: true,
result: response.data
};
} catch (error) {
console.error('Audio emotion analysis error:', error);
return {
success: false,
error: 'Не удалось проанализировать аудио'
};
}
}
/**
* Анализ эмоций по изображению лица
*/
async analyzeFace(imageBlob) {
try {
const formData = new FormData();
formData.append('image', imageBlob, 'face.jpg');
const response = await axios.post(`${this.apiUrl}/face`, formData, {
headers: {
...this.headers,
'Content-Type': 'multipart/form-data'
}
});
return {
success: true,
result: response.data
};
} catch (error) {
console.error('Face emotion analysis error:', error);
return {
success: false,
error: 'Не удалось проанализировать изображение лица'
};
}
}
/**
* Комплексный анализ эмоций (мультимодальный)
*/
async analyzeMultimodal(text, audioBlob, imageBlob, context = {}) {
try {
const formData = new FormData();
if (text) {
formData.append('text', text);
}
if (audioBlob) {
formData.append('audio', audioBlob, 'recording.wav');
}
if (imageBlob) {
formData.append('image', imageBlob, 'face.jpg');
}
formData.append('context', JSON.stringify(context));
const response = await axios.post(`${this.apiUrl}/multimodal`, formData, {
headers: {
...this.headers,
'Content-Type': 'multipart/form-data'
}
});
return {
success: true,
result: response.data
};
} catch (error) {
console.error('Multimodal emotion analysis error:', error);
return {
success: false,
error: 'Не удалось выполнить комплексный анализ эмоций'
};
}
}
/**
* Получение рекомендаций на основе распознанных эмоций
*/
async getRecommendations(emotionData) {
try {
const response = await axios.post(`${this.apiUrl}/recommendations`, {
emotionData
}, {
headers: this.headers
});
return {
success: true,
recommendations: response.data.recommendations
};
} catch (error) {
console.error('Recommendations error:', error);
return {
success: false,
error: 'Не удалось получить рекомендации'
};
}
}
}
export default new EmotionService();
// src/components/EmotionRecognition.jsx
// Компонент системы распознавания эмоций
import React, { useState, useEffect, useRef } from 'react';
import { Container, Row, Col, Card, Button, Form, Alert, Tabs, Tab, ProgressBar, Badge } from 'react-bootstrap';
import { FaCamera, FaMicrophone, FaComment, FaBrain, FaSync, FaInfoCircle } from 'react-icons/fa';
import { Line } from 'react-chartjs-2';
import 'chart.js/auto';
import EmotionService from '../services/emotionService';
const EmotionRecognition = () => {
const [activeTab, setActiveTab] = useState('text');
const [textInput, setTextInput] = useState('');
const [isRecording, setIsRecording] = useState(false);
const [audioBlob, setAudioBlob] = useState(null);
const [faceImage, setFaceImage] = useState(null);
const [emotionResult, setEmotionResult] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const [recommendations, setRecommendations] = useState([]);
const [userId] = useState(`user_${Math.random().toString(36).substr(2, 9)}`);
const videoRef = useRef(null);
const mediaRecorderRef = useRef(null);
const chunksRef = useRef([]);
// Запуск видеопотока для захвата лица
useEffect(() => {
const startVideo = async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
if (videoRef.current) {
videoRef.current.srcObject = stream;
}
} catch (err) {
console.error('Error accessing webcam:', err);
setError('Не удалось получить доступ к камере. Пожалуйста, разрешите доступ к камере в настройках браузера.');
}
};
startVideo();
return () => {
if (videoRef.current && videoRef.current.srcObject) {
videoRef.current.srcObject.getTracks().forEach(track => track.stop());
}
};
}, []);
// Обработка отправки текста
const handleTextSubmit = async (e) => {
e.preventDefault();
if (!textInput.trim() || isLoading) return;
setIsLoading(true);
setError(null);
try {
const response = await EmotionService.analyzeText(textInput);
if (response.success) {
setEmotionResult(response.result);
fetchRecommendations(response.result);
} else {
setError(response.error);
}
} catch (err) {
setError('Произошла ошибка при анализе текста. Пожалуйста, попробуйте еще раз.');
console.error('Text analysis error:', err);
} finally {
setIsLoading(false);
}
};
// Запуск записи аудио
const startRecording = async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorderRef.current = new MediaRecorder(stream);
chunksRef.current = [];
mediaRecorderRef.current.ondataavailable = (e) => {
if (e.data.size > 0) {
chunksRef.current.push(e.data);
}
};
mediaRecorderRef.current.onstop = () => {
const blob = new Blob(chunksRef.current, { type: 'audio/wav' });
setAudioBlob(blob);
// Автоматически анализируем аудио
analyzeAudio(blob);
};
mediaRecorderRef.current.start(1000);
setIsRecording(true);
} catch (err) {
setError('Не удалось получить доступ к микрофону. Пожалуйста, разрешите доступ к микрофону в настройках браузера.');
console.error('Microphone access error:', err);
}
};
// Остановка записи аудио
const stopRecording = () => {
if (mediaRecorderRef.current && isRecording) {
mediaRecorderRef.current.stop();
setIsRecording(false);
// Останавливаем аудио-треки
const tracks = mediaRecorderRef.current.stream.getTracks();
tracks.forEach(track => track.stop());
}
};
// Анализ аудио
const analyzeAudio = async (blob) => {
setIsLoading(true);
setError(null);
try {
const response = await EmotionService.analyzeAudio(blob);
if (response.success) {
setEmotionResult(response.result);
fetchRecommendations(response.result);
} else {
setError(response.error);
}
} catch (err) {
setError('Произошла ошибка при анализе аудио. Пожалуйста, попробуйте еще раз.');
console.error('Audio analysis error:', err);
} finally {
setIsLoading(false);
}
};
// Анализ лица
const analyzeFace = async () => {
if (!videoRef.current) return;
setIsLoading(true);
setError(null);
try {
// Создаем canvas для захвата изображения
const canvas = document.createElement('canvas');
canvas.width = videoRef.current.videoWidth;
canvas.height = videoRef.current.videoHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(videoRef.current, 0, 0, canvas.width, canvas.height);
// Конвертируем в Blob
canvas.toBlob(async (blob) => {
setFaceImage(URL.createObjectURL(blob));
// Анализируем изображение
const response = await EmotionService.analyzeFace(blob);
if (response.success) {
setEmotionResult(response.result);
fetchRecommendations(response.result);
} else {
setError(response.error);
}
setIsLoading(false);
}, 'image/jpeg', 0.95);
} catch (err) {
setError('Произошла ошибка при анализе лица. Пожалуйста, попробуйте еще раз.');
console.error('Face analysis error:', err);
setIsLoading(false);
}
};
// Комплексный анализ
const analyzeMultimodal = async () => {
setIsLoading(true);
setError(null);
try {
// Захватываем изображение лица
let faceBlob = null;
if (videoRef.current) {
const canvas = document.createElement('canvas');
canvas.width = videoRef.current.videoWidth;
canvas.height = videoRef.current.videoHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(videoRef.current, 0, 0, canvas.width, canvas.height);
canvas.toBlob(blob => faceBlob = blob, 'image/jpeg', 0.95);
}
// Контекст для анализа
const context = {
userId,
currentTopic: "general_conversation",
culturalBackground: "western"
};
const response = await EmotionService.analyzeMultimodal(
textInput,
audioBlob,
faceBlob,
context
);
if (response.success) {
setEmotionResult(response.result);
fetchRecommendations(response.result);
} else {
setError(response.error);
}
} catch (err) {
setError('Произошла ошибка при комплексном анализе. Пожалуйста, попробуйте еще раз.');
console.error('Multimodal analysis error:', err);
} finally {
setIsLoading(false);
}
};
// Получение рекомендаций
const fetchRecommendations = async (emotionData) => {
try {
const response = await EmotionService.getRecommendations(emotionData);
if (response.success) {
setRecommendations(response.recommendations);
}
} catch (err) {
console.error('Failed to fetch recommendations:', err);
}
};
// Подготовка данных для графика
const getChartData























