Spaces:
Sleeping
Sleeping
Commit
·
2eb6f71
1
Parent(s):
379c1ed
Implementada estructura modular con controladores y modelos de datos siguiendo la versión local
Browse files- app.py +5 -0
- controllers/__init__.py +1 -0
- controllers/group_analysis_controller.py +33 -0
- controllers/ui_controller.py +73 -0
- data_models/__init__.py +1 -0
- data_models/context_member.py +76 -0
- data_models/image_context.py +66 -0
app.py
CHANGED
|
@@ -23,6 +23,11 @@ from utils.export_utils import export_to_json, export_to_csv, get_download_link,
|
|
| 23 |
from utils.preprocessing_ui import display_preprocessing_comparison, setup_preprocessing_controls, display_processing_status, get_processing_image, show_preprocessing_ui
|
| 24 |
from services.database_service import DatabaseService
|
| 25 |
from services.image_service import ImageService
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
# Definimos funciones básicas de reemplazo para no alterar el código
|
| 28 |
def display_image_with_controls(image, caption=None, use_column_width=True, title=None, allow_zoom=False, allow_download=False):
|
|
|
|
| 23 |
from utils.preprocessing_ui import display_preprocessing_comparison, setup_preprocessing_controls, display_processing_status, get_processing_image, show_preprocessing_ui
|
| 24 |
from services.database_service import DatabaseService
|
| 25 |
from services.image_service import ImageService
|
| 26 |
+
# Agregamos las importaciones de los módulos de controladores y modelos de datos
|
| 27 |
+
from controllers.ui_controller import UIController
|
| 28 |
+
from controllers.group_analysis_controller import GroupAnalysisController
|
| 29 |
+
from data_models.image_context import ImageContext
|
| 30 |
+
from data_models.context_member import ContextMember
|
| 31 |
|
| 32 |
# Definimos funciones básicas de reemplazo para no alterar el código
|
| 33 |
def display_image_with_controls(image, caption=None, use_column_width=True, title=None, allow_zoom=False, allow_download=False):
|
controllers/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
# Controllers package
|
controllers/group_analysis_controller.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Group Analysis Controller Module for EmotionMirror application.
|
| 3 |
+
|
| 4 |
+
This module contains the GroupAnalysisController class that manages the group analysis
|
| 5 |
+
features of the application.
|
| 6 |
+
"""
|
| 7 |
+
import streamlit as st
|
| 8 |
+
import logging
|
| 9 |
+
from typing import Dict, Any, Optional, List
|
| 10 |
+
import numpy as np
|
| 11 |
+
|
| 12 |
+
from services.history_service import HistoryService
|
| 13 |
+
|
| 14 |
+
class GroupAnalysisController:
|
| 15 |
+
"""
|
| 16 |
+
Controller for managing group analysis of multiple faces.
|
| 17 |
+
Handles detection, analysis and display of group emotion data.
|
| 18 |
+
"""
|
| 19 |
+
|
| 20 |
+
def __init__(self, history_service=None):
|
| 21 |
+
"""
|
| 22 |
+
Initialize the group analysis controller.
|
| 23 |
+
|
| 24 |
+
Args:
|
| 25 |
+
history_service: Optional HistoryService for managing history data
|
| 26 |
+
"""
|
| 27 |
+
self.history_service = history_service or HistoryService()
|
| 28 |
+
|
| 29 |
+
def run(self):
|
| 30 |
+
"""Run the group analysis controller and handle its operations."""
|
| 31 |
+
# Group analysis is not required for the immediate issue fix
|
| 32 |
+
# This is a minimal implementation for module compatibility
|
| 33 |
+
pass
|
controllers/ui_controller.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
UI Controller Module for EmotionMirror application.
|
| 3 |
+
|
| 4 |
+
This module contains the UIController class that manages the user interface components
|
| 5 |
+
and interactions throughout the application.
|
| 6 |
+
"""
|
| 7 |
+
import streamlit as st
|
| 8 |
+
import logging
|
| 9 |
+
from typing import Dict, Any, Optional
|
| 10 |
+
import numpy as np
|
| 11 |
+
from PIL import Image
|
| 12 |
+
import io
|
| 13 |
+
import os
|
| 14 |
+
import base64
|
| 15 |
+
from datetime import datetime
|
| 16 |
+
|
| 17 |
+
from services.image_service import ImageService
|
| 18 |
+
from services.database_service import DatabaseService
|
| 19 |
+
|
| 20 |
+
class UIController:
|
| 21 |
+
"""
|
| 22 |
+
Controller for managing the user interface components of the application.
|
| 23 |
+
Handles the setup and display of UI elements throughout the app.
|
| 24 |
+
"""
|
| 25 |
+
|
| 26 |
+
def __init__(
|
| 27 |
+
self,
|
| 28 |
+
image_service: Optional[ImageService] = None,
|
| 29 |
+
database_service: Optional[DatabaseService] = None,
|
| 30 |
+
config: Optional[Dict[str, Any]] = None
|
| 31 |
+
):
|
| 32 |
+
"""
|
| 33 |
+
Initialize the UI controller with optional service dependencies.
|
| 34 |
+
|
| 35 |
+
Args:
|
| 36 |
+
image_service: Optional ImageService instance for image processing
|
| 37 |
+
database_service: Optional service for database operations
|
| 38 |
+
config: Optional configuration dictionary with app settings
|
| 39 |
+
"""
|
| 40 |
+
self.image_service = image_service or ImageService()
|
| 41 |
+
self.database_service = database_service or DatabaseService()
|
| 42 |
+
self.config = config or {}
|
| 43 |
+
|
| 44 |
+
def setup_image_upload_interface(self):
|
| 45 |
+
"""
|
| 46 |
+
Set up and display the image upload interface with validation feedback.
|
| 47 |
+
|
| 48 |
+
Returns:
|
| 49 |
+
The uploaded file object if an image was successfully uploaded and validated
|
| 50 |
+
"""
|
| 51 |
+
# Create file uploader
|
| 52 |
+
uploaded_file = st.file_uploader(
|
| 53 |
+
"Choose an image...",
|
| 54 |
+
type=["jpg", "jpeg", "png"],
|
| 55 |
+
help="Upload a clear image of a face for analysis."
|
| 56 |
+
)
|
| 57 |
+
|
| 58 |
+
if uploaded_file is not None:
|
| 59 |
+
# Validate image file
|
| 60 |
+
validation_result = self.image_service.validate_image_file(
|
| 61 |
+
uploaded_file,
|
| 62 |
+
check_content=True,
|
| 63 |
+
check_dimensions=True
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
# If validation failed, show issues
|
| 67 |
+
if not validation_result["valid"]:
|
| 68 |
+
st.error("Image validation failed:")
|
| 69 |
+
for issue in validation_result["issues"]:
|
| 70 |
+
st.warning(issue)
|
| 71 |
+
return None
|
| 72 |
+
|
| 73 |
+
return uploaded_file
|
data_models/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
# Data models package
|
data_models/context_member.py
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Context Member Model for EmotionMirror application.
|
| 3 |
+
|
| 4 |
+
This module defines the ContextMember class that represents
|
| 5 |
+
a member (person) in a group analysis context.
|
| 6 |
+
"""
|
| 7 |
+
from typing import Dict, Any, Optional
|
| 8 |
+
from datetime import datetime
|
| 9 |
+
|
| 10 |
+
class ContextMember:
|
| 11 |
+
"""
|
| 12 |
+
Represents a member (person) in a group analysis context.
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
def __init__(
|
| 16 |
+
self,
|
| 17 |
+
member_id: str,
|
| 18 |
+
name: Optional[str] = None,
|
| 19 |
+
face_data: Optional[Dict[str, Any]] = None,
|
| 20 |
+
emotion_data: Optional[Dict[str, float]] = None,
|
| 21 |
+
metadata: Optional[Dict[str, Any]] = None
|
| 22 |
+
):
|
| 23 |
+
"""
|
| 24 |
+
Initialize a context member.
|
| 25 |
+
|
| 26 |
+
Args:
|
| 27 |
+
member_id: Unique identifier for the member
|
| 28 |
+
name: Name of the person if known
|
| 29 |
+
face_data: Face detection data including coordinates, etc.
|
| 30 |
+
emotion_data: Emotion analysis results
|
| 31 |
+
metadata: Additional member metadata
|
| 32 |
+
"""
|
| 33 |
+
self.member_id = member_id
|
| 34 |
+
self.name = name or "Unknown"
|
| 35 |
+
self.face_data = face_data or {}
|
| 36 |
+
self.emotion_data = emotion_data or {}
|
| 37 |
+
self.metadata = metadata or {}
|
| 38 |
+
self.created_at = datetime.now()
|
| 39 |
+
|
| 40 |
+
def to_dict(self) -> Dict[str, Any]:
|
| 41 |
+
"""
|
| 42 |
+
Convert the context member to a dictionary for storage or serialization.
|
| 43 |
+
|
| 44 |
+
Returns:
|
| 45 |
+
Dictionary representation of the context member
|
| 46 |
+
"""
|
| 47 |
+
return {
|
| 48 |
+
"member_id": self.member_id,
|
| 49 |
+
"name": self.name,
|
| 50 |
+
"face_data": self.face_data,
|
| 51 |
+
"emotion_data": self.emotion_data,
|
| 52 |
+
"metadata": self.metadata,
|
| 53 |
+
"created_at": self.created_at.isoformat()
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
@classmethod
|
| 57 |
+
def from_dict(cls, data: Dict[str, Any]) -> 'ContextMember':
|
| 58 |
+
"""
|
| 59 |
+
Create a context member from a dictionary.
|
| 60 |
+
|
| 61 |
+
Args:
|
| 62 |
+
data: Dictionary with context member data
|
| 63 |
+
|
| 64 |
+
Returns:
|
| 65 |
+
A ContextMember instance
|
| 66 |
+
"""
|
| 67 |
+
instance = cls(
|
| 68 |
+
member_id=data.get("member_id", ""),
|
| 69 |
+
name=data.get("name", "Unknown"),
|
| 70 |
+
face_data=data.get("face_data", {}),
|
| 71 |
+
emotion_data=data.get("emotion_data", {}),
|
| 72 |
+
metadata=data.get("metadata", {})
|
| 73 |
+
)
|
| 74 |
+
if "created_at" in data:
|
| 75 |
+
instance.created_at = datetime.fromisoformat(data["created_at"])
|
| 76 |
+
return instance
|
data_models/image_context.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Image Context Model for EmotionMirror application.
|
| 3 |
+
|
| 4 |
+
This module defines the ImageContext class that represents
|
| 5 |
+
an image analysis context including metadata and results.
|
| 6 |
+
"""
|
| 7 |
+
from typing import Dict, Any, List, Optional
|
| 8 |
+
from datetime import datetime
|
| 9 |
+
|
| 10 |
+
class ImageContext:
|
| 11 |
+
"""
|
| 12 |
+
Represents an image context for analysis including metadata and results.
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
def __init__(
|
| 16 |
+
self,
|
| 17 |
+
image_id: str,
|
| 18 |
+
timestamp: Optional[datetime] = None,
|
| 19 |
+
metadata: Optional[Dict[str, Any]] = None,
|
| 20 |
+
faces: Optional[List[Dict[str, Any]]] = None
|
| 21 |
+
):
|
| 22 |
+
"""
|
| 23 |
+
Initialize an image context.
|
| 24 |
+
|
| 25 |
+
Args:
|
| 26 |
+
image_id: Unique identifier for the image
|
| 27 |
+
timestamp: Time when the image was processed
|
| 28 |
+
metadata: Image metadata like dimensions, format, etc.
|
| 29 |
+
faces: List of detected faces and their analysis
|
| 30 |
+
"""
|
| 31 |
+
self.image_id = image_id
|
| 32 |
+
self.timestamp = timestamp or datetime.now()
|
| 33 |
+
self.metadata = metadata or {}
|
| 34 |
+
self.faces = faces or []
|
| 35 |
+
|
| 36 |
+
def to_dict(self) -> Dict[str, Any]:
|
| 37 |
+
"""
|
| 38 |
+
Convert the image context to a dictionary for storage or serialization.
|
| 39 |
+
|
| 40 |
+
Returns:
|
| 41 |
+
Dictionary representation of the image context
|
| 42 |
+
"""
|
| 43 |
+
return {
|
| 44 |
+
"image_id": self.image_id,
|
| 45 |
+
"timestamp": self.timestamp.isoformat(),
|
| 46 |
+
"metadata": self.metadata,
|
| 47 |
+
"faces": self.faces
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
@classmethod
|
| 51 |
+
def from_dict(cls, data: Dict[str, Any]) -> 'ImageContext':
|
| 52 |
+
"""
|
| 53 |
+
Create an image context from a dictionary.
|
| 54 |
+
|
| 55 |
+
Args:
|
| 56 |
+
data: Dictionary with image context data
|
| 57 |
+
|
| 58 |
+
Returns:
|
| 59 |
+
An ImageContext instance
|
| 60 |
+
"""
|
| 61 |
+
return cls(
|
| 62 |
+
image_id=data.get("image_id", ""),
|
| 63 |
+
timestamp=datetime.fromisoformat(data.get("timestamp", datetime.now().isoformat())),
|
| 64 |
+
metadata=data.get("metadata", {}),
|
| 65 |
+
faces=data.get("faces", [])
|
| 66 |
+
)
|