Spaces:
Sleeping
Sleeping
| """ | |
| Page Handlers Module for EmotionMirror application. | |
| This module contains handler functions for different pages in the EmotionMirror application. | |
| Following the principle of modularization, each page's logic is separated into its own function. | |
| """ | |
| import logging | |
| import streamlit as st | |
| import cv2 | |
| import numpy as np | |
| from utils.preprocessing_ui import show_preprocessing_ui, get_processing_image | |
| from utils.image_visualization import display_image_with_controls, create_image_tabs, handle_image_viewer | |
| from PIL import Image | |
| import io | |
| import os | |
| import json | |
| import time | |
| from typing import Dict, Any | |
| from datetime import datetime | |
| from utils.export_utils import export_to_json, export_to_csv, get_download_link, generate_emotion_summary | |
| logger = logging.getLogger(__name__) | |
| def handle_visual_analysis(agent_manager, image_service, db_service, uploaded_file=None): | |
| """ | |
| Handle the Visual Analysis page logic. | |
| Args: | |
| agent_manager: The agent manager instance | |
| image_service: The image service instance | |
| db_service: The database service instance | |
| uploaded_file: The uploaded file, if any | |
| """ | |
| st.header("Visual Emotion Analysis") | |
| st.markdown(""" | |
| Upload an image to analyze emotions. | |
| For best results, use a clear image of a face with good lighting. | |
| """) | |
| # Ensure agent_manager is properly initialized | |
| if not agent_manager: | |
| st.error("Agent manager is not initialized correctly. Please refresh the page.") | |
| return | |
| # Initialize the visual agent at the start | |
| visual_agent = agent_manager.get_agent("VisualAgent") | |
| if not visual_agent: | |
| st.warning("Visual agent not available. The system is initializing or there is a configuration issue.") | |
| logger.error("Failed to get VisualAgent from agent_manager") | |
| # Create numbered sections to match local version | |
| st.subheader("1. Upload an Image") | |
| # Add reset button for clearing current image | |
| if "original_image" in st.session_state: | |
| col1, col2 = st.columns([3, 1]) | |
| with col2: | |
| if st.button("Clear Current Image", key="clear_image"): | |
| # Clear the session state | |
| if "original_image" in st.session_state: | |
| del st.session_state["original_image"] | |
| if "processed_image" in st.session_state: | |
| del st.session_state["processed_image"] | |
| if "current_image_path" in st.session_state: | |
| del st.session_state["current_image_path"] | |
| st.experimental_rerun() | |
| # Create file uploader | |
| if uploaded_file is None: | |
| uploaded_file = st.file_uploader( | |
| "Choose an image...", | |
| type=["jpg", "jpeg", "png"], | |
| help="Upload a clear image of a face for analysis." | |
| ) | |
| # Display information about detection methods | |
| with st.expander("About the Detection Methods", expanded=False): | |
| st.markdown(""" | |
| ### About the Detection Methods | |
| Currently using: **Advanced Detection** | |
| * **Basic detection** is faster but less accurate. It works by analyzing simple facial features. | |
| * **Advanced detection (DeepFace)** uses deep learning models that are trained on thousands of faces to recognize subtle emotional cues. | |
| You can change the default detection method in the sidebar settings. | |
| """) | |
| # Display image and interface when uploaded | |
| if uploaded_file is not None: | |
| try: | |
| # Process the uploaded file | |
| file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8) | |
| uploaded_file.seek(0) # Reset the file pointer for further processing | |
| # Validate image file - includes format, size, and dimensions | |
| validation_result = image_service.validate_image_file( | |
| uploaded_file, | |
| check_content=True, | |
| check_dimensions=True | |
| ) | |
| # If the image is valid, process it | |
| if validation_result["valid"]: | |
| # Process the uploaded image to improve quality if possible | |
| try: | |
| # Load image for processing with OpenCV (this will be in BGR format) | |
| img = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR) | |
| # Convert from BGR to RGB for preprocessing display | |
| img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) | |
| # Store original RGB image for display | |
| if "original_image" not in st.session_state: | |
| st.session_state.original_image = img_rgb.copy() | |
| # Determine which image to process based on preprocessing settings | |
| use_improved = st.session_state.get("use_improved_image", False) | |
| # Choose image for processing | |
| img_to_process = get_processing_image(img_rgb, image_service, use_improved) | |
| # Comentamos esta sección para eliminar la imagen grande | |
| """ | |
| # Check if we have both original and processed images | |
| if "processed_image" in st.session_state: | |
| # Create tabs to display original and processed images | |
| image_tabs_result = create_image_tabs( | |
| st.session_state.original_image, | |
| st.session_state.processed_image | |
| ) | |
| else: | |
| # Display just the original image | |
| display_result = display_image_with_controls( | |
| st.session_state.original_image, | |
| title="Uploaded Image", | |
| allow_zoom=True, | |
| allow_download=True | |
| ) | |
| # Store the processed image if available for comparison | |
| if use_improved and img_to_process is not None: | |
| st.session_state.processed_image = img_to_process | |
| """ | |
| # Display image analysis from validation | |
| st.subheader("3. Image Analysis") | |
| analysis_expander = st.expander("View Image Analysis Details", expanded=False) | |
| with analysis_expander: | |
| # Show image metadata | |
| if "image_metadata" in validation_result: | |
| metadata = validation_result["image_metadata"] | |
| st.markdown("#### Image Details") | |
| # Create columns for metadata display | |
| meta_cols = st.columns(3) | |
| with meta_cols[0]: | |
| st.markdown("**Dimensions**") | |
| width = metadata.get("width", 0) | |
| height = metadata.get("height", 0) | |
| st.write(f"{width} × {height}") | |
| with meta_cols[1]: | |
| st.markdown("**Format**") | |
| img_format = metadata.get("format", "Unknown") | |
| st.write(f"{img_format}") | |
| with meta_cols[2]: | |
| st.markdown("**Size**") | |
| size_kb = metadata.get("size_kb", 0) | |
| st.write(f"{size_kb:.1f} KB") | |
| # Quality metrics if available | |
| if "quality" in metadata: | |
| st.markdown("#### Quality Metrics") | |
| quality = metadata["quality"] | |
| # Create columns for quality metrics | |
| metric_cols = st.columns(3) | |
| with metric_cols[0]: | |
| st.markdown("**Sharpness**") | |
| sharpness = int(quality.get("sharpness", 0) * 100) | |
| st.write(f"{sharpness}%") | |
| with metric_cols[1]: | |
| st.markdown("**Brightness**") | |
| brightness = int(quality.get("brightness", 0) * 100) | |
| st.write(f"{brightness}%") | |
| with metric_cols[2]: | |
| st.markdown("**Contrast**") | |
| contrast = int(quality.get("contrast", 0.26) * 100) | |
| st.write(f"{contrast}%") | |
| # Add space between sections | |
| st.markdown("<div style='height: 20px;'></div>", unsafe_allow_html=True) | |
| # NOW display the preprocessing UI AFTER the Image Analysis section | |
| st.subheader("4. Image Preprocessing") | |
| preprocessing_result = show_preprocessing_ui(image_service, img_rgb) | |
| if not preprocessing_result.get("success", False): | |
| st.error(f"Error in preprocessing: {preprocessing_result.get('message', 'Unknown error')}") | |
| # Store path in session state for future use | |
| if "current_image_path" not in st.session_state: | |
| # Save the file for reference | |
| save_path = image_service.save_uploaded_image(img_to_process) | |
| st.session_state["current_image_path"] = save_path | |
| # Add some space to improve layout | |
| st.markdown("<div style='height: 20px;'></div>", unsafe_allow_html=True) | |
| # Analysis section | |
| st.subheader("5. Emotion Analysis") | |
| st.info("Image successfully uploaded. Emotion analysis functionality will be available soon.") | |
| # Add a disabled button as placeholder for future functionality | |
| st.button("Analyze Emotions (Coming Soon)", disabled=True, key="analyze_button") | |
| except Exception as e: | |
| logger.error(f"Error processing image: {e}", exc_info=True) | |
| st.error(f"Error processing image: {str(e)}") | |
| else: | |
| # Show validation issues | |
| st.error("Image validation failed:") | |
| for issue in validation_result["issues"]: | |
| st.warning(issue) | |
| except Exception as e: | |
| logger.error(f"Error in Visual Analysis: {e}", exc_info=True) | |
| st.error(f"Error processing image: {str(e)}") | |
| def handle_history_page(db_service): | |
| """ | |
| Handle the History page logic. | |
| Args: | |
| db_service: The database service instance | |
| """ | |
| st.header("Analysis History") | |
| st.markdown("View your previous analyses and export results.") | |
| # Create tabs for different views - Using numbered sequence for clear navigation | |
| history_tabs = ["1. Recent Analyses", "2. Statistics", "3. Export Data"] | |
| tab1, tab2, tab3 = st.tabs(history_tabs) | |
| with tab1: | |
| # Implementation of recent analyses tab | |
| pass # Implement the rest of the history page functionality | |
| with tab2: | |
| # Implementation of statistics tab | |
| pass # Implement statistics functionality | |
| with tab3: | |
| # Implementation of export data tab | |
| pass # Implement export functionality | |
| def handle_about_page(): | |
| """Handle the About page logic.""" | |
| st.header("About EmotionMirror") | |
| st.markdown(""" | |
| EmotionMirror is an application that uses computer vision to analyze emotions in facial expressions. | |
| **Version:** 0.1.3 (Phase 1.3) | |
| **Features:** | |
| - Facial emotion detection using computer vision | |
| - Support for image uploads | |
| - Analysis history and data export | |
| - Image preprocessing for improved detection | |
| **Technology:** | |
| - Python | |
| - OpenCV for image processing | |
| - Deep learning models for emotion classification | |
| - Streamlit for the user interface | |
| """) | |