File size: 3,342 Bytes
25e6afd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import cv2
import numpy as np
import base64
import logging
from deepface import DeepFace
from typing import Dict, Tuple, Optional

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger("EmotionProcessor")

class EmotionProcessor:
    def __init__(self):
        """Initialize the emotion processor."""
        try:
            # Load face cascade classifier
            self.face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
            logger.info("Emotion processor initialized successfully")
        except Exception as e:
            logger.error(f"Failed to initialize emotion processor: {e}")
            raise
    
    def process_base64_image(self, base64_image: str) -> Tuple[Optional[str], Optional[Dict]]:
        """Process a base64 encoded image and return the dominant emotion."""
        try:
            # Remove data URL prefix if present
            if ',' in base64_image:
                base64_image = base64_image.split(',')[1]
            
            # Decode base64 image
            img_data = base64.b64decode(base64_image)
            nparr = np.frombuffer(img_data, np.uint8)
            frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
            
            if frame is None:
                logger.error("Failed to decode image")
                return None, None
            
            return self.process_frame(frame)
            
        except Exception as e:
            logger.error(f"Error processing base64 image: {e}")
            return None, None
    
    def process_frame(self, frame) -> Tuple[Optional[str], Optional[Dict]]:
        """Process a frame and return the dominant emotion."""
        try:
            # Convert frame to grayscale
            gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            
            # Convert grayscale frame to RGB format
            rgb_frame = cv2.cvtColor(gray_frame, cv2.COLOR_GRAY2RGB)
            
            # Detect faces in the frame
            faces = self.face_cascade.detectMultiScale(gray_frame, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
            
            if len(faces) == 0:
                logger.info("No faces detected")
                return "neutral", None
            
            # Process the first face
            x, y, w, h = faces[0]
            
            # Extract the face ROI (Region of Interest)
            face_roi = rgb_frame[y:y + h, x:x + w]
            
            # Perform emotion analysis on the face ROI
            result = DeepFace.analyze(face_roi, actions=['emotion'], enforce_detection=False)
            
            # Determine the dominant emotion
            emotion = result[0]['dominant_emotion']
            emotion_scores = result[0]['emotion']
            
            logger.info(f"Detected emotion: {emotion}")
            
            return emotion, emotion_scores
            
        except Exception as e:
            logger.error(f"Error processing frame: {e}")
            return "neutral", None

# For testing
if __name__ == "__main__":
    processor = EmotionProcessor()
    # Test with a sample image if available
    # result = processor.process_frame(cv2.imread('sample.jpg'))
    # print(f"Detected emotion: {result}")