Spaces:
Sleeping
Sleeping
| """ | |
| Facial Emotion Analysis API for ShantiView | |
| Wraps the DeepFace-based facial emotion detection model | |
| """ | |
| import cv2 | |
| import logging | |
| import numpy as np | |
| from deepface import DeepFace | |
| logger = logging.getLogger(__name__) | |
| # Confidence threshold for emotion detection | |
| CONFIDENCE_THRESHOLD = 30.0 | |
| def _convert_to_native_types(data): | |
| """Convert numpy types to Python native types for JSON serialization.""" | |
| if isinstance(data, dict): | |
| return {k: _convert_to_native_types(v) for k, v in data.items()} | |
| elif isinstance(data, list): | |
| return [_convert_to_native_types(item) for item in data] | |
| elif isinstance(data, (np.float32, np.float64)): | |
| return float(data) | |
| elif isinstance(data, (np.int32, np.int64)): | |
| return int(data) | |
| elif isinstance(data, np.ndarray): | |
| return data.tolist() | |
| else: | |
| return data | |
| def analyze_frame_api(image_path: str) -> dict: | |
| """ | |
| Analyze an image file for facial emotion detection. | |
| Args: | |
| image_path: Path to the image file | |
| Returns: | |
| Dictionary with detection results (JSON serializable) | |
| """ | |
| try: | |
| # Read the image | |
| frame = cv2.imread(image_path) | |
| if frame is None: | |
| return { | |
| "detected": False, | |
| "emotion": "No image", | |
| "score": 0.0, | |
| "message": "Could not read image file" | |
| } | |
| # Analyze using DeepFace | |
| results = DeepFace.analyze( | |
| frame, | |
| actions=['emotion'], | |
| enforce_detection=False, | |
| silent=True | |
| ) | |
| # Process results | |
| if results and isinstance(results, list) and len(results) > 0: | |
| result = results[0] | |
| dominant_emotion = str(result.get('dominant_emotion', 'unknown')) | |
| emotion_scores = result.get('emotion', {}) | |
| emotion_score = float(emotion_scores.get(dominant_emotion, 0.0)) | |
| # Check confidence threshold | |
| detected = emotion_score >= CONFIDENCE_THRESHOLD | |
| emotion = dominant_emotion if detected else "Uncertain" | |
| # Convert all_emotions to native Python types | |
| all_emotions = {} | |
| for k, v in emotion_scores.items(): | |
| all_emotions[str(k)] = float(v) / 100.0 | |
| return { | |
| "detected": True, | |
| "emotion": emotion.capitalize(), | |
| "score": float(emotion_score) / 100.0, # Convert to 0-1 scale | |
| "all_emotions": _convert_to_native_types(all_emotions) | |
| } | |
| else: | |
| return { | |
| "detected": False, | |
| "emotion": "No face", | |
| "score": 0.0, | |
| "message": "No face detected in image" | |
| } | |
| except Exception as e: | |
| logger.error(f"Error in facial analysis: {e}") | |
| return { | |
| "detected": False, | |
| "emotion": "Error", | |
| "score": 0.0, | |
| "message": str(e) | |
| } | |