psypredict-backend / app /services /emotion_engine.py
therandomuser03's picture
Initial clean commit with LFS models
0c46c35
import os
import cv2
import numpy as np
import logging
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.image import img_to_array
# Define the exact labels from your notebook
EMOTION_LABELS = ['happy', 'sad', 'angry', 'surprised', 'neutral', 'fear', 'disgust']
class EmotionDetector:
def __init__(self):
self.model = None
self.face_cascade = None
self.load_resources()
def load_resources(self):
"""Loads the ML model and Haar Cascade from the assets folder."""
# Dynamic path to ensure it works on any machine
base_path = os.path.dirname(os.path.abspath(__file__))
assets_path = os.path.join(base_path, '..', 'ml_assets')
model_path = os.path.join(assets_path, 'emotion_model_trained.h5')
haar_path = os.path.join(assets_path, 'haarcascade_frontalface_default.xml')
# Load Model
try:
self.model = load_model(model_path)
logging.info(f"✅ Emotion Model loaded from {model_path}")
except Exception as e:
logging.error(f"❌ Failed to load model: {e}")
# Load Face Detector
try:
self.face_cascade = cv2.CascadeClassifier(haar_path)
if self.face_cascade.empty():
raise IOError("Failed to load Haarcascade XML file")
logging.info(f"✅ Face Detector loaded from {haar_path}")
except Exception as e:
logging.error(f"❌ Failed to load Haarcascade: {e}")
def detect_emotion(self, image_path_or_array):
"""
Input: Image (numpy array or file path)
Output: Dictionary with 'emotion' and 'confidence'
"""
if self.model is None or self.face_cascade is None:
return {"error": "AI models are not loaded"}
# 1. Read Image
if isinstance(image_path_or_array, str):
image = cv2.imread(image_path_or_array)
else:
image = image_path_or_array
if image is None:
return {"error": "Invalid image input"}
# 2. Convert to Grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 3. Detect Face
faces = self.face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)
if len(faces) == 0:
return {"message": "No face detected"}
# 4. Process the first detected face
(x, y, w, h) = faces[0]
roi_gray = gray[y:y+h, x:x+w]
# 5. Preprocessing (Resize to 48x48 & Normalize)
roi = cv2.resize(roi_gray, (48, 48), interpolation=cv2.INTER_AREA)
roi = roi.astype("float") / 255.0
roi = img_to_array(roi)
roi = np.expand_dims(roi, axis=0)
# 6. Predict
preds = self.model.predict(roi)[0]
label_index = preds.argmax()
label = EMOTION_LABELS[label_index]
confidence = float(preds[label_index])
return {
"emotion": label,
"confidence": round(confidence * 100, 2),
"face_box": [int(x), int(y), int(w), int(h)]
}
# Create a singleton instance to be imported elsewhere
emotion_detector = EmotionDetector()