Team Ai
Apppublic

jarondon82/ComputerVisionProject

sourceHugging Faceupdated 2y agoView on Hugging Face
1likes
streamlit_app.py.bak2501 linesDownload Raw Back to root
1import streamlit as st2import cv23import numpy as np4from PIL import Image5from io import BytesIO6import base647import tempfile8import os9import time10import urllib.request11import matplotlib.pyplot as plt12import pickle13from sklearn.metrics.pairwise import cosine_similarity # type: ignore14import pandas as pd15import av16from streamlit_webrtc import webrtc_streamer, VideoProcessorBase, RTCConfiguration, WebRtcMode17 18# Importar las utilidades para la base de datos de rostros19try:20    from face_database_utils import save_face_database, load_face_database, export_database_json, import_database_json, print_database_info21    DATABASE_UTILS_AVAILABLE = True22except ImportError:23    DATABASE_UTILS_AVAILABLE = False24    st.warning("Database utilities are not available. Face recognition data will not be persistent between sessions.")25 26# Importar DeepFace para reconocimiento facial avanzado27try:28    from deepface import DeepFace29    DEEPFACE_AVAILABLE = True30except ImportError:31    DEEPFACE_AVAILABLE = False32 33# Import functions for face comparison34try:35    from face_comparison import compare_faces, compare_faces_embeddings, generate_comparison_report_english, draw_face_matches, extract_face_embeddings, extract_face_embeddings_all_models36    FACE_COMPARISON_AVAILABLE = True37except ImportError:38    FACE_COMPARISON_AVAILABLE = False39    st.warning("Face comparison functions are not available. Please check your installation.")40 41# Función principal que encapsula toda la aplicación42def main():43    # Set page config with custom title and layout44    st.set_page_config(45        page_title="Advanced Face & Feature Detection",46        page_icon="👤",47        layout="wide",48        initial_sidebar_state="expanded"49    )50    51    # Sidebar for navigation and controls52    st.sidebar.title("Controls & Settings")53 54    # Initialize session_state to store original image and camera state55    if 'original_image' not in st.session_state:56        st.session_state.original_image = None57    if 'camera_running' not in st.session_state:58        st.session_state.camera_running = False59    if 'feature_camera_running' not in st.session_state:60        st.session_state.feature_camera_running = False61 62    # Navigation menu63    app_mode = st.sidebar.selectbox(64        "Choose the app mode",65        ["About", "Face Detection", "Feature Detection", "Comparison Mode", "Face Recognition"]66    )67 68    # Function to load DNN models with caching and auto-download69    @st.cache_resource70    def load_face_model():71        # No need to create directory as we're using the root directory72        #73            #74        75        # Correct model file names76        modelFile = "res10_300x300_ssd_iter_140000.caffemodel"77        configFile = "deploy.prototxt.txt"78        79        # Check if files exist80        missing_files = []81        if not os.path.exists(modelFile):82            missing_files.append(modelFile)83        if not os.path.exists(configFile):84            missing_files.append(configFile)85        86        if missing_files:87            st.error("Missing model files: " + ", ".join(missing_files))88            st.error("Please manually download the following files:")89            st.code("""90            1. Download the model file:91               URL: https://raw.githubusercontent.com/sr6033/face-detection-with-OpenCV-and-DNN/master/res10_300x300_ssd_iter_140000.caffemodel92               Save as: res10_300x300_ssd_iter_140000.caffemodel93               94            2. Download the configuration file:95               URL: https://raw.githubusercontent.com/sr6033/face-detection-with-OpenCV-and-DNN/master/deploy.prototxt.txt96               Save as: deploy.prototxt.txt97            """)98            st.stop()99        100        # Load model101        try:102            net = cv2.dnn.readNetFromCaffe(configFile, modelFile)103            return net104        except Exception as e:105            st.error(f"Error loading model: {e}")106            st.stop()107 108    @st.cache_resource109    def load_feature_models():110        # Load pre-trained models for eye and smile detection111        eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye.xml')112        smile_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_smile.xml')113        return eye_cascade, smile_cascade114 115    # Function for detecting faces in an image116    def detect_face_dnn(net, frame, conf_threshold=0.5):117        """118        Detecta rostros usando el modelo DNN y devuelve las detecciones.119        """120        try:121            # Verificar que el frame sea válido122            if frame is None or frame.size == 0 or frame.shape[0] == 0 or frame.shape[1] == 0:123                return []124                125            # Crear blob a partir del frame (redimensionar a 300x300, escalar, etc.)126            blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), [104, 117, 123], False, False)127            128            # Establecer la entrada para la red neuronal129            net.setInput(blob)130            131            # Realizar la detección132            detections = net.forward()133            134            # Procesar las detecciones para devolver una lista de bounding boxes135            bboxes = []136            frame_h = frame.shape[0]137            frame_w = frame.shape[1]138            139            for i in range(detections.shape[2]):140                confidence = detections[0, 0, i, 2]141                if confidence > conf_threshold:142                    x1 = int(detections[0, 0, i, 3] * frame_w)143                    y1 = int(detections[0, 0, i, 4] * frame_h)144                    x2 = int(detections[0, 0, i, 5] * frame_w)145                    y2 = int(detections[0, 0, i, 6] * frame_h)146                    147                    # Asegurarse de que las coordenadas estén dentro de los límites148                    x1 = max(0, min(x1, frame_w - 1))149                    y1 = max(0, min(y1, frame_h - 1))150                    x2 = max(0, min(x2, frame_w - 1))151                    y2 = max(0, min(y2, frame_h - 1))152                    153                    # Añadir el bounding box y la confianza154                    bboxes.append([x1, y1, x2, y2, confidence])155            156            return bboxes157        except Exception as e:158            st.error(f"Error en la detección de rostros: {e}")159            return []160 161    # Function for processing face detections162    def process_face_detections(frame, detections, conf_threshold=0.5, bbox_color=(0, 255, 0)):163        # Create a copy for drawing on164        result_frame = frame.copy()165        166        # Procesar detecciones si son del formato original167        if isinstance(detections, np.ndarray) and len(detections.shape) == 4:168            bboxes = []169            frame_h = frame.shape[0]170            frame_w = frame.shape[1]171            172            for i in range(detections.shape[2]):173                confidence = detections[0, 0, i, 2]174                if confidence > conf_threshold:175                    x1 = int(detections[0, 0, i, 3] * frame_w)176                    y1 = int(detections[0, 0, i, 4] * frame_h)177                    x2 = int(detections[0, 0, i, 5] * frame_w)178                    y2 = int(detections[0, 0, i, 6] * frame_h)179                    180                    # Asegurarse de que las coordenadas estén dentro de los límites181                    x1 = max(0, min(x1, frame_w - 1))182                    y1 = max(0, min(y1, frame_h - 1))183                    x2 = max(0, min(x2, frame_w - 1))184                    y2 = max(0, min(y2, frame_h - 1))185                    186                    # Dibujar el bounding box187                    cv2.rectangle(result_frame, (x1, y1), (x2, y2), bbox_color, 2)188                    189                    # Añadir texto con la confianza190                    label = f"{confidence:.2f}"191                    cv2.putText(result_frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, bbox_color, 2)192                    193                    # Añadir a la lista de bounding boxes194                    bboxes.append([x1, y1, x2, y2, confidence])195        else:196            # Si ya es una lista de bounding boxes (formato nuevo)197            bboxes = detections198            # Dibujar bounding boxes199            for bbox in bboxes:200                if len(bbox) == 5:  # Asegurarse de que el bounding box tiene el formato correcto201                    x1, y1, x2, y2, confidence = bbox202                    if confidence >= conf_threshold:203                        # Dibujar el bounding box204                        cv2.rectangle(result_frame, (x1, y1), (x2, y2), bbox_color, 2)205                        206                        # Añadir texto con la confianza207                        label = f"{confidence:.2f}"208                        cv2.putText(result_frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, bbox_color, 2)209        210        return result_frame, bboxes211 212    # Function to detect facial features (eyes, smile) with improved profile face handling213    def detect_facial_features(frame, bboxes, eye_cascade, smile_cascade, detect_eyes=True, detect_smile=True, smile_sensitivity=15, eye_sensitivity=5):214        result_frame = frame.copy()215        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)216        217        # Counters for detection summary218        eye_count = 0219        smile_count = 0220        221        for bbox in bboxes:222            x1, y1, x2, y2, _ = bbox223            roi_gray = gray[y1:y2, x1:x2]224            roi_color = result_frame[y1:y2, x1:x2]225            face_width = x2 - x1226            face_height = y2 - y1227            228            # Detect eyes if enabled229            if detect_eyes:230                # Adjust region of interest to focus on the upper part of the face231                upper_face_y1 = y1232                upper_face_y2 = y1 + int(face_height * 0.55)  # Slightly reduced to focus more on the eye area233                234                # For profile faces, we need to search the entire upper region235                # as well as the left and right sides separately236                237                # Full upper region for profile faces238                upper_face_roi_gray = gray[upper_face_y1:upper_face_y2, x1:x2]239                upper_face_roi_color = result_frame[upper_face_y1:upper_face_y2, x1:x2]240                241                # Split the upper region into two halves (left and right) to search for eyes individually242                mid_x = x1 + face_width // 2243                left_eye_roi_gray = gray[upper_face_y1:upper_face_y2, x1:mid_x]244                right_eye_roi_gray = gray[upper_face_y1:upper_face_y2, mid_x:x2]245                246                left_eye_roi_color = result_frame[upper_face_y1:upper_face_y2, x1:mid_x]247                right_eye_roi_color = result_frame[upper_face_y1:upper_face_y2, mid_x:x2]248                249                # Apply histogram equalization and contrast enhancement for all regions250                if upper_face_roi_gray.size > 0:251                    upper_face_roi_gray = cv2.equalizeHist(upper_face_roi_gray)252                    253                    # Enhance contrast254                    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))255                    upper_face_roi_gray = clahe.apply(upper_face_roi_gray)256                    257                    # First try to detect eyes in the full upper region (for profile faces)258                    full_eyes = eye_cascade.detectMultiScale(259                        upper_face_roi_gray, 260                        scaleFactor=1.02,  # More sensitive for profile faces261                        minNeighbors=max(1, eye_sensitivity-3),  # Even more sensitive262                        minSize=(int(face_width * 0.07), int(face_width * 0.07)),263                        maxSize=(int(face_width * 0.3), int(face_width * 0.3))264                    )265                    266                    # If we found eyes in the full region, use those267                    if len(full_eyes) > 0:268                        # Sort by size (area) and take up to 2 largest269                        full_eyes = sorted(full_eyes, key=lambda e: e[2] * e[3], reverse=True)270                        full_eyes = full_eyes[:2]  # Take at most 2 eyes271                        272                        for ex, ey, ew, eh in full_eyes:273                            eye_count += 1274                            cv2.rectangle(upper_face_roi_color, (ex, ey), (ex+ew, ey+eh), (255, 0, 0), 2)275                            cv2.putText(upper_face_roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)276                    else:277                        # If no eyes found in full region, try left and right separately278                        if left_eye_roi_gray.size > 0:279                            left_eye_roi_gray = cv2.equalizeHist(left_eye_roi_gray)280                            left_eye_roi_gray = clahe.apply(left_eye_roi_gray)281                            282                            left_eyes = eye_cascade.detectMultiScale(283                                left_eye_roi_gray, 284                                scaleFactor=1.03,285                                minNeighbors=max(1, eye_sensitivity-2),286                                minSize=(int(face_width * 0.08), int(face_width * 0.08)),287                                maxSize=(int(face_width * 0.25), int(face_width * 0.25))288                            )289                            290                            if len(left_eyes) > 0:291                                # Sort by size and take the largest292                                left_eyes = sorted(left_eyes, key=lambda e: e[2] * e[3], reverse=True)293                                left_eye = left_eyes[0]294                                eye_count += 1295                                296                                # Draw rectangle for the left eye297                                ex, ey, ew, eh = left_eye298                                cv2.rectangle(left_eye_roi_color, (ex, ey), (ex+ew, ey+eh), (255, 0, 0), 2)299                                cv2.putText(left_eye_roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)300                        301                        if right_eye_roi_gray.size > 0:302                            right_eye_roi_gray = cv2.equalizeHist(right_eye_roi_gray)303                            right_eye_roi_gray = clahe.apply(right_eye_roi_gray)304                            305                            right_eyes = eye_cascade.detectMultiScale(306                                right_eye_roi_gray, 307                                scaleFactor=1.03,308                                minNeighbors=max(1, eye_sensitivity-2),309                                minSize=(int(face_width * 0.08), int(face_width * 0.08)),310                                maxSize=(int(face_width * 0.25), int(face_width * 0.25))311                            )312                            313                            if len(right_eyes) > 0:314                                # Sort by size and take the largest315                                right_eyes = sorted(right_eyes, key=lambda e: e[2] * e[3], reverse=True)316                                right_eye = right_eyes[0]317                                eye_count += 1318                                319                                # Draw rectangle for the right eye320                                ex, ey, ew, eh = right_eye321                                cv2.rectangle(right_eye_roi_color, (ex, ey), (ex+ew, ey+eh), (255, 0, 0), 2)322                                cv2.putText(right_eye_roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)323            324            # Detect smile if enabled325            if detect_smile:326                # For profile faces, we need to adjust the region of interest327                # Try multiple regions to improve detection328                329                # Standard region (middle to bottom)330                lower_face_y1 = y1 + int(face_height * 0.5)331                lower_face_roi_gray = gray[lower_face_y1:y2, x1:x2]332                lower_face_roi_color = result_frame[lower_face_y1:y2, x1:x2]333                334                # Alternative region (lower third)335                alt_lower_face_y1 = y1 + int(face_height * 0.65)336                alt_lower_face_roi_gray = gray[alt_lower_face_y1:y2, x1:x2]337                338                # Apply histogram equalization and enhance contrast339                smile_detected = False340                341                if lower_face_roi_gray.size > 0:342                    lower_face_roi_gray = cv2.equalizeHist(lower_face_roi_gray)343                    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))344                    lower_face_roi_gray = clahe.apply(lower_face_roi_gray)345                    346                    # Try with standard parameters347                    smiles = smile_cascade.detectMultiScale(348                        lower_face_roi_gray, 349                        scaleFactor=1.2,350                        minNeighbors=smile_sensitivity,351                        minSize=(int(face_width * 0.25), int(face_width * 0.15)),352                        maxSize=(int(face_width * 0.7), int(face_width * 0.4))353                    )354                    355                    if len(smiles) > 0:356                        # Sort by size and take the largest357                        smiles = sorted(smiles, key=lambda s: s[2] * s[3], reverse=True)358                        sx, sy, sw, sh = smiles[0]359                        360                        # Increment smile counter361                        smile_count += 1362                        smile_detected = True363                        364                        # Draw rectangle for the smile365                        cv2.rectangle(lower_face_roi_color, (sx, sy), (sx+sw, sy+sh), (0, 0, 255), 2)366                        cv2.putText(lower_face_roi_color, "Smile", (sx, sy-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)367                368                # If no smile detected in standard region, try alternative region369                if not smile_detected and alt_lower_face_roi_gray.size > 0:370                    alt_lower_face_roi_gray = cv2.equalizeHist(alt_lower_face_roi_gray)371                    alt_lower_face_roi_gray = clahe.apply(alt_lower_face_roi_gray)372                    373                    # Try with more sensitive parameters374                    alt_smiles = smile_cascade.detectMultiScale(375                        alt_lower_face_roi_gray, 376                        scaleFactor=1.1,377                        minNeighbors=max(1, smile_sensitivity-5),  # More sensitive378                        minSize=(int(face_width * 0.2), int(face_width * 0.1)),379                        maxSize=(int(face_width * 0.6), int(face_width * 0.3))380                    )381                    382                    if len(alt_smiles) > 0:383                        # Sort by size and take the largest384                        alt_smiles = sorted(alt_smiles, key=lambda s: s[2] * s[3], reverse=True)385                        sx, sy, sw, sh = alt_smiles[0]386                        387                        # Adjust coordinates for the alternative region388                        adjusted_sy = sy + (alt_lower_face_y1 - lower_face_y1)389                        390                        # Increment smile counter391                        smile_count += 1392                        393                        # Draw rectangle for the smile (in the original lower face ROI)394                        cv2.rectangle(lower_face_roi_color, (sx, adjusted_sy), (sx+sw, adjusted_sy+sh), (0, 0, 255), 2)395                        cv2.putText(lower_face_roi_color, "Smile", (sx, adjusted_sy-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)396        397        return result_frame, eye_count, smile_count398 399    # Función para detectar atributos faciales (edad, género, emoción)400    def detect_face_attributes(image, bbox):401        """402        Detecta atributos faciales como edad, género y emoción usando DeepFace.403        404        Args:405            image: Imagen en formato OpenCV (BGR)406            bbox: Bounding box de la cara [x1, y1, x2, y2, conf]407            408        Returns:409            Diccionario con los atributos detectados410        """411        if not DEEPFACE_AVAILABLE:412            return None413        414        try:415            x1, y1, x2, y2, _ = bbox416            face_img = image[y1:y2, x1:x2]417            418            # Convertir de BGR a RGB para DeepFace419            face_img_rgb = cv2.cvtColor(face_img, cv2.COLOR_BGR2RGB)420            421            # Analyze atributos faciales422            attributes = DeepFace.analyze(423                img_path=face_img_rgb,424                actions=['age', 'gender', 'emotion'],425                enforce_detection=False,426                detector_backend="opencv"427            )428            429            return attributes[0]430        431        except Exception as e:432            st.error(f"Error detecting facial attributes: {str(e)}")433            return None434 435    # Function to apply age and gender detection (placeholder - would need additional models)436    def detect_age_gender(frame, bboxes):437        # Versión mejorada que usa DeepFace si está disponible438        result_frame = frame.copy()439        440        for i, bbox in enumerate(bboxes):441            x1, y1, x2, y2, _ = bbox442            443            if DEEPFACE_AVAILABLE:444                # Intentar usar DeepFace para análisis facial445                attributes = detect_face_attributes(frame, bbox)446                447                if attributes:448                    # Extraer información de atributos449                    age = attributes.get('age', 'Unknown')450                    gender = attributes.get('gender', 'Unknown')451                    emotion = attributes.get('dominant_emotion', 'Unknown').capitalize()452                    gender_prob = attributes.get('gender', {}).get('Woman', 0)453                    454                    # Determinar color basado en confianza455                    if gender == 'Woman':456                        gender_color = (255, 0, 255)  # Magenta para mujer457                    else:458                        gender_color = (255, 0, 0)    # Azul para hombre459                    460                    # Añadir texto con información461                    cv2.putText(result_frame, f"Age: {age}", (x1, y2+20), 462                               cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2)463                    cv2.putText(result_frame, f"Gender: {gender}", (x1, y2+40), 464                               cv2.FONT_HERSHEY_SIMPLEX, 0.5, gender_color, 2)465                    cv2.putText(result_frame, f"Emotion: {emotion}", (x1, y2+60), 466                               cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 2)467                else:468                    # Fallback si DeepFace falla469                    cv2.putText(result_frame, "Age: Unknown", (x1, y2+20), 470                               cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 2)471                    cv2.putText(result_frame, "Gender: Unknown", (x1, y2+40), 472                               cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 2)473            else:474                # Usar texto placeholder si DeepFace no está disponible475                cv2.putText(result_frame, "Age: 25-35", (x1, y2+20), 476                           cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 2)477                cv2.putText(result_frame, "Gender: Unknown", (x1, y2+40), 478                           cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 2)479        480        return result_frame481 482    # Function to generate download link for processed image483    def get_image_download_link(img, filename, text):484        buffered = BytesIO()485        img.save(buffered, format="JPEG")486        img_str = base64.b64encode(buffered.getvalue()).decode()487        href = f'<a href="data:file/txt;base64,{img_str}" download="{filename}">{text}</a>'488        return href489 490    # Function to process video frames491    def process_video(video_path, face_net, eye_cascade, smile_cascade, conf_threshold=0.5, detect_eyes=True, detect_smile=True, bbox_color=(0, 255, 0), smile_sensitivity=15, eye_sensitivity=5):492        cap = cv2.VideoCapture(video_path)493        494        # Get video properties495        frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))496        frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))497        fps = int(cap.get(cv2.CAP_PROP_FPS))498        499        # Create temporary output file500        temp_dir = tempfile.mkdtemp()501        temp_output_path = os.path.join(temp_dir, "processed_video.mp4")502        503        # Initialize video writer504        fourcc = cv2.VideoWriter_fourcc(*'mp4v')505        out = cv2.VideoWriter(temp_output_path, fourcc, fps, (frame_width, frame_height))506        507        # Create a progress bar508        frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))509        progress_bar = st.progress(0)510        status_text = st.empty()511        512        # Process video frames513        current_frame = 0514        processing_times = []515        516        # Total counters for statistics517        total_faces = 0518        total_eyes = 0519        total_smiles = 0520        521        while cap.isOpened():522            ret, frame = cap.read()523            if not ret:524                break525            526            # Start timing for performance metrics527            start_time = time.time()528            529            # Detect faces530            detections = detect_face_dnn(face_net, frame, conf_threshold)531            processed_frame, bboxes = process_face_detections(frame, detections, conf_threshold, bbox_color)532            533            # Update face counter534            total_faces += len(bboxes)535            536            # Detect facial features if enabled537            if detect_eyes or detect_smile:538                processed_frame, eye_count, smile_count = detect_facial_features(539                    processed_frame, 540                    bboxes, 541                    eye_cascade, 542                    smile_cascade,543                    detect_eyes,544                    detect_smile,545                    smile_sensitivity,546                    eye_sensitivity547                )548                # Update counters549                total_eyes += eye_count550                total_smiles += smile_count551            552            # End timing553            processing_times.append(time.time() - start_time)554            555            # Write the processed frame556            out.write(processed_frame)557            558            # Update progress559            current_frame += 1560            progress_bar.progress(current_frame / frame_count)561            status_text.text(f"Processing frame {current_frame}/{frame_count}")562        563        # Release resources564        cap.release()565        out.release()566        567        # Calculate and display performance metrics568        if processing_times:569            avg_time = sum(processing_times) / len(processing_times)570            status_text.text(f"Processing complete! Average processing time: {avg_time:.4f}s per frame")571        572        # Return detection statistics573        detection_stats = {574            "faces": total_faces // max(1, current_frame),  # Average per frame575            "eyes": total_eyes // max(1, current_frame),    # Average per frame576            "smiles": total_smiles // max(1, current_frame) # Average per frame577        }578        579        return temp_output_path, temp_dir, detection_stats580 581    # Camera control functions582    def start_camera():583        st.session_state.camera_running = True584 585    def stop_camera():586        st.session_state.camera_running = False587        st.session_state.camera_stopped = True588 589    def start_feature_camera():590        st.session_state.feature_camera_running = True591 592    def stop_feature_camera():593        st.session_state.feature_camera_running = False594        st.session_state.feature_camera_stopped = True595 596    # Función auxiliar para verificar si una imagen es válida antes de redimensionar597    def is_valid_image(img):598        if img is None:599            return False600        try:601            # Verificar que la imagen tenga dimensiones válidas y datos602            return img.size > 0 and len(img.shape) >= 2 and img.shape[0] > 0 and img.shape[1] > 0603        except:604            return False605    606    # Función auxiliar para redimensionar de forma segura607    def safe_resize(img, target_size):608        if is_valid_image(img):609            try:610                return cv2.resize(img, target_size)611            except Exception as e:612                st.error(f"Error al redimensionar: {str(e)}")613                return None614        return None615 616    if app_mode == "About":617        st.markdown("""618        ## About This App619        620        This application uses OpenCV's Deep Neural Network (DNN) module and Haar Cascade classifiers to detect faces and facial features in images and videos.621        622        ### Features:623        - Face detection using OpenCV DNN624        - Eye and smile detection using Haar Cascades625        - Support for both image and video processing626        - Adjustable confidence threshold627        - Download options for processed media628        - Performance metrics629        630        ### How to use:631        1. Select a mode from the sidebar632        2. Upload an image or video633        3. Adjust settings as needed634        4. View and download the results635        636        ### Technologies Used:637        - Streamlit for the web interface638        - OpenCV for computer vision operations639        - Python for backend processing640        641        ### Models:642        - SSD MobileNet for face detection643        - Haar Cascades for facial features644        """)645        646        # Display a sample image or GIF647        st.image("https://opencv.org/wp-content/uploads/2019/07/detection.gif", caption="Sample face detection", use_container_width=True)648 649    elif app_mode == "Face Detection":650        # Load the face detection model651        face_net = load_face_model()652        653        # Input type selection (Image or Video)654        input_type = st.sidebar.radio("Select Input Type", ["Image", "Video"])655        656        # Confidence threshold slider657        conf_threshold = st.sidebar.slider(658            "Confidence Threshold", 659            min_value=0.0, 660            max_value=1.0, 661            value=0.5, 662            step=0.05,663            help="Adjust the threshold for face detection confidence (higher = fewer detections but more accurate)"664        )665        666        # Style options667        bbox_color = st.sidebar.color_picker("Bounding Box Color", "#00FF00")668        # Convert hex color to BGR for OpenCV669        bbox_color_rgb = tuple(int(bbox_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))670        bbox_color_bgr = (bbox_color_rgb[2], bbox_color_rgb[1], bbox_color_rgb[0])  # Convert RGB to BGR671        672        # Display processing metrics673        show_metrics = st.sidebar.checkbox("Show Processing Metrics", True)674        675        if input_type == "Image":676            # File uploader for images677            file_buffer = st.file_uploader("Upload an image", type=['jpg', 'jpeg', 'png'])678            679            if file_buffer is not None:680                # Read the file and convert it to OpenCV format681                raw_bytes = np.asarray(bytearray(file_buffer.read()), dtype=np.uint8)682                image = cv2.imdecode(raw_bytes, cv2.IMREAD_COLOR)683                684                # Save la imagen original en session_state para reprocesarla cuando cambie el umbral685                # Usar un identificador único para cada archivo para detectar cambios686                file_id = file_buffer.name + str(file_buffer.size)687                688                if 'file_id' not in st.session_state or st.session_state.file_id != file_id:689                    st.session_state.file_id = file_id690                    st.session_state.original_image = image.copy()691                692                # Display original image693                col1, col2 = st.columns(2)694                with col1:695                    st.subheader("Original Image")696                    st.image(st.session_state.original_image, channels='BGR', use_container_width=True)697                698                # Start timing for performance metrics699                start_time = time.time()700                701                # Detect faces702                detections = detect_face_dnn(face_net, st.session_state.original_image, conf_threshold)703                processed_image, bboxes = process_face_detections(st.session_state.original_image, detections, conf_threshold, bbox_color_bgr)704                705                # Calculate processing time706                processing_time = time.time() - start_time707                708                # Display the processed image709                with col2:710                    st.subheader("Processed Image")711                    st.image(processed_image, channels='BGR', use_container_width=True)712                    713                    # Convert OpenCV image to PIL for download714                    pil_img = Image.fromarray(processed_image[:, :, ::-1])715                    st.markdown(716                        get_image_download_link(pil_img, "face_detection_result.jpg", "📥 Download Processed Image"),717                        unsafe_allow_html=True718                    )719                720                # Show metrics if enabled721                if show_metrics:722                    st.subheader("Processing Metrics")723                    col1, col2, col3 = st.columns(3)724                    col1.metric("Processing Time", f"{processing_time:.4f} seconds")725                    col2.metric("Faces Detected", len(bboxes))726                    col3.metric("Confidence Threshold", f"{conf_threshold:.2f}")727                    728                    # Display detailed metrics in an expandable section729                    with st.expander("Detailed Detection Information"):730                        if bboxes:731                            st.write("Detected faces with confidence scores:")732                            for i, bbox in enumerate(bboxes):733                                st.write(f"Face #{i+1}: Confidence = {bbox[4]:.4f}")734                        else:735                            st.write("No faces detected in the image.")736        737        else:  # Video mode738            # Video mode options739            video_source = st.radio("Select video source", ["Upload video", "Use webcam"])740            741            if video_source == "Upload video":742                # File uploader for videos743                file_buffer = st.file_uploader("Upload a video", type=['mp4', 'avi', 'mov'])744                745                if file_buffer is not None:746                    # Save uploaded video to temporary file747                    temp_dir = tempfile.mkdtemp()748                    temp_path = os.path.join(temp_dir, "input_video.mp4")749                    750                    with open(temp_path, "wb") as f:751                        f.write(file_buffer.read())752                    753                    # Display original video754                    st.subheader("Original Video")755                    st.video(temp_path)756                    757                    # Load models for feature detection (will be used in the processing)758                    eye_cascade, smile_cascade = load_feature_models()759                    760                    # Process video button761                    if st.button("Process Video"):762                        with st.spinner("Processing video... This may take a while depending on the video length."):763                            # Process the video764                            output_path, output_dir, detection_stats = process_video(765                                temp_path, 766                                face_net, 767                                eye_cascade,768                                smile_cascade,769                                conf_threshold,770                                detect_eyes=True,771                                detect_smile=True,772                                bbox_color=bbox_color_bgr,773                                eye_sensitivity=5774                            )775                            776                            # Display processed video777                            st.subheader("Processed Video")778                            st.video(output_path)779                            780                            # Mostrar estadísticas de detección781                            st.subheader("Detection Summary")782                            summary_col1, summary_col2, summary_col3 = st.columns(3)783                            summary_col1.metric("Avg. Faces per Frame", detection_stats["faces"])784                            785                            if detect_eyes: # type: ignore786                                summary_col2.metric("Avg. Eyes per Frame", detection_stats["eyes"])787                            else:788                                summary_col2.metric("Eyes Detected", "N/A")789                            790                            if detect_smile: # type: ignore791                                summary_col3.metric("Avg. Smiles per Frame", detection_stats["smiles"])792                            else:793                                summary_col3.metric("Smiles Detected", "N/A")794                            795                            # Provide download link796                            with open(output_path, 'rb') as f:797                                video_bytes = f.read()798                            799                            st.download_button(800                                label="📥 Download Processed Video",801                                data=video_bytes,802                                file_name="processed_video.mp4",803                                mime="video/mp4"804                            )805                            806                            # Clean up temporary files807                            try:808                                os.remove(temp_path)809                                os.remove(output_path)810                                os.rmdir(temp_dir)811                                os.rmdir(output_dir)812                            except:813                                pass814            else:  # Use webcam815                st.subheader("Real-time face detection")816                st.write("Click 'Start Camera' to begin real-time face detection.")817                818                # Placeholder for webcam video819                camera_placeholder = st.empty()820                821                # Buttons to control the camera822                col1, col2 = st.columns(2)823                start_button = col1.button("Start Camera", on_click=start_camera)824                stop_button = col2.button("Stop Camera", on_click=stop_camera)825                826                # Show message when camera is stopped827                if 'camera_stopped' in st.session_state and st.session_state.camera_stopped:828                    st.info("Camera stopped. Click 'Start Camera' to activate it again.")829                    st.session_state.camera_stopped = False830                831                if st.session_state.camera_running:832                    st.info("Camera activated. Processing real-time video...")833                    # Initialize webcam834                    cap = cv2.VideoCapture(0)  # 0 is typically the main webcam835                    836                    if not cap.isOpened():837                        st.error("Could not access webcam. Make sure it's connected and not being used by another application.")838                        st.warning("⚠️ Note: If you're using this app on Hugging Face Spaces, webcam access is not supported. Try running this app locally for webcam features.")839                        st.session_state.camera_running = False840                    else:841                        # Display real-time video with face detection842                        try:843                            while st.session_state.camera_running:844                                ret, frame = cap.read()845                                if not ret:846                                    st.error("Error reading frame from camera.")847                                    break848                                849                                # Detect faces850                                detections = detect_face_dnn(face_net, frame, conf_threshold)851                                processed_frame, bboxes = process_face_detections(frame, detections, conf_threshold, bbox_color_bgr)852                                853                                # Display the processed frame854                                camera_placeholder.image(processed_frame, channels="BGR", use_container_width=True)855                                856                                # Small pause to avoid overloading the CPU857                                time.sleep(0.01)858                        finally:859                            # Release the camera when stopped860                            cap.release()861 862    elif app_mode == "Feature Detection":863        # Load all required models864        face_net = load_face_model()865        eye_cascade, smile_cascade = load_feature_models()866        867        # Feature selection checkboxes868        st.sidebar.subheader("Feature Detection Options")869        detect_eyes = st.sidebar.checkbox("Detect Eyes", True)870        871        # Add controls for eye detection sensitivity872        eye_sensitivity = 5  # Default value873        if detect_eyes:874            eye_sensitivity = st.sidebar.slider(875                "Eye Detection Sensitivity", 876                min_value=1, 877                max_value=10, 878                value=5, 879                step=1,880                help="Adjust the sensitivity of eye detection (lower value = more detections)"881            )882        883        detect_smile = st.sidebar.checkbox("Detect Smile", True)884        885        # Add controls for smile detection sensitivity886        smile_sensitivity = 15  # Default value887        if detect_smile:888            smile_sensitivity = st.sidebar.slider(889                "Smile Detection Sensitivity", 890                min_value=5, 891                max_value=30, 892                value=15, 893                step=1,894                help="Adjust the sensitivity of smile detection (lower value = more detections)"895            )896        897        detect_age_gender_option = st.sidebar.checkbox("Detect Age/Gender (Demo)", False)898        899        # Confidence threshold slider900        conf_threshold = st.sidebar.slider(901            "Face Detection Confidence", 902            min_value=0.0, 903            max_value=1.0, 904            value=0.5, 905            step=0.05906        )907        908        # Style options909        bbox_color = st.sidebar.color_picker("Bounding Box Color", "#00FF00")910        # Convert hex color to BGR for OpenCV911        bbox_color_rgb = tuple(int(bbox_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))912        bbox_color_bgr = (bbox_color_rgb[2], bbox_color_rgb[1], bbox_color_rgb[0])  # Convert RGB to BGR913        914        # Input type selection915        input_type = st.sidebar.radio("Select Input Type", ["Image", "Video"])916        917        if input_type == "Image":918            # File uploader for images919            file_buffer = st.file_uploader("Upload an image", type=['jpg', 'jpeg', 'png'])920            921            if file_buffer is not None:922                # Read the file and convert it to OpenCV format923                raw_bytes = np.asarray(bytearray(file_buffer.read()), dtype=np.uint8)924                image = cv2.imdecode(raw_bytes, cv2.IMREAD_COLOR)925                926                # Save la imagen original en session_state para reprocesarla cuando cambie el umbral927                # Usar un identificador único para cada archivo para detectar cambios928                file_id = file_buffer.name + str(file_buffer.size)929                930                if 'feature_file_id' not in st.session_state or st.session_state.feature_file_id != file_id:931                    st.session_state.feature_file_id = file_id932                    st.session_state.feature_original_image = image.copy()933                934                # Display original image935                col1, col2 = st.columns(2)936                with col1:937                    st.subheader("Original Image")938                    st.image(st.session_state.feature_original_image, channels='BGR', use_container_width=True)939                940                # Start processing with face detection941                detections = detect_face_dnn(face_net, st.session_state.feature_original_image, conf_threshold)942                processed_image, bboxes = process_face_detections(st.session_state.feature_original_image, detections, conf_threshold, bbox_color_bgr)943                944                # Inicializar contadores945                eye_count = 0946                smile_count = 0947                948                # Detect facial features if any options are enabled949                if detect_eyes or detect_smile:950                    processed_image, eye_count, smile_count = detect_facial_features(951                        processed_image, 952                        bboxes,953                        eye_cascade,954                        smile_cascade,955                        detect_eyes,956                        detect_smile,957                        smile_sensitivity,958                        eye_sensitivity959                    )960                    961                # Apply age/gender detection if enabled (demo purpose)962                if detect_age_gender_option:963                    processed_image = detect_age_gender(processed_image, bboxes)964                965                # Display the processed image966                with col2:967                    st.subheader("Processed Image")968                    st.image(processed_image, channels='BGR', use_container_width=True)969                    970                    # Convert OpenCV image to PIL for download971                    pil_img = Image.fromarray(processed_image[:, :, ::-1])972                    st.markdown(973                        get_image_download_link(pil_img, "feature_detection_result.jpg", "📥 Download Processed Image"),974                        unsafe_allow_html=True975                    )976                977                # Display detection summary978                st.subheader("Detection Summary")979                summary_col1, summary_col2, summary_col3 = st.columns(3)980                summary_col1.metric("Faces Detected", len(bboxes))981                982                if detect_eyes:983                    summary_col2.metric("Eyes Detected", eye_count)984                else:985                    summary_col2.metric("Eyes Detected", "N/A")986                987                if detect_smile:988                    summary_col3.metric("Smiles Detected", smile_count)989                else:990                    summary_col3.metric("Smiles Detected", "N/A")991        992        else:  # Video mode993            st.write("Facial feature detection in video")994            995            # Video mode options996            video_source = st.radio("Select video source", ["Upload video", "Use webcam"])997            998            if video_source == "Upload video":999                st.write("Upload a video to process with facial feature detection.")1000                # Similar implementation to Face Detection mode for uploaded videos1001                file_buffer = st.file_uploader("Upload a video", type=['mp4', 'avi', 'mov'])1002                1003                if file_buffer is not None:1004                    # Save uploaded video to temporary file1005                    temp_dir = tempfile.mkdtemp()1006                    temp_path = os.path.join(temp_dir, "input_video.mp4")1007                    1008                    with open(temp_path, "wb") as f:1009                        f.write(file_buffer.read())1010                    1011                    # Display original video1012                    st.subheader("Original Video")1013                    st.video(temp_path)1014                    1015                    # Process video button1016                    if st.button("Process Video"):1017                        with st.spinner("Processing video... This may take a while depending on the video length."):1018                            # Process the video with feature detection1019                            output_path, output_dir, detection_stats = process_video(1020                                temp_path, 1021                                face_net, 1022                                eye_cascade,1023                                smile_cascade,1024                                conf_threshold,1025                                detect_eyes=True,1026                                detect_smile=True,1027                                bbox_color=bbox_color_bgr,1028                                smile_sensitivity=smile_sensitivity,1029                                eye_sensitivity=eye_sensitivity1030                            )1031                            1032                            # Display processed video1033                            st.subheader("Processed Video")1034                            st.video(output_path)1035                            1036                            # Mostrar estadísticas de detección1037                            st.subheader("Detection Summary")1038                            summary_col1, summary_col2, summary_col3 = st.columns(3)1039                            summary_col1.metric("Avg. Faces per Frame", detection_stats["faces"])1040                            1041                            if detect_eyes:1042                                summary_col2.metric("Avg. Eyes per Frame", detection_stats["eyes"])1043                            else:1044                                summary_col2.metric("Eyes Detected", "N/A")1045                            1046                            if detect_smile:1047                                summary_col3.metric("Avg. Smiles per Frame", detection_stats["smiles"])1048                            else:1049                                summary_col3.metric("Smiles Detected", "N/A")1050                            1051                            # Provide download link1052                            with open(output_path, 'rb') as f:1053                                video_bytes = f.read()1054                            1055                            st.download_button(1056                                label="📥 Download Processed Video",1057                                data=video_bytes,1058                                file_name="feature_detection_video.mp4",1059                                mime="video/mp4"1060                            )1061                            1062                            # Clean up temporary files1063                            try:1064                                os.remove(temp_path)1065                                os.remove(output_path)1066                                os.rmdir(temp_dir)1067                                os.rmdir(output_dir)1068                            except:1069                                pass1070            else:  # Usar cámara web1071                st.subheader("Real-time facial feature detection")1072                st.write("Click 'Start Camera' to begin real-time detection.")1073                1074                # Placeholder for webcam video1075                camera_placeholder = st.empty()1076                1077                # Buttons to control the camera1078                col1, col2 = st.columns(2)1079                start_button = col1.button("Start Camera", on_click=start_feature_camera)1080                stop_button = col2.button("Stop Camera", on_click=stop_feature_camera)1081                1082                # Show message when camera is stopped1083                if 'feature_camera_stopped' in st.session_state and st.session_state.feature_camera_stopped:1084                    st.info("Camera stopped. Click 'Start Camera' to activate it again.")1085                    st.session_state.feature_camera_stopped = False1086                1087                if st.session_state.feature_camera_running:1088                    st.info("Camera activated. Processing real-time video with feature detection...")1089                    # Initialize webcam1090                    cap = cv2.VideoCapture(0)  # 0 is typically the main webcam1091                    1092                    if not cap.isOpened():1093                        st.error("Could not access webcam. Make sure it's connected and not being used by another application.")1094                        st.warning("⚠️ Note: If you're using this app on Hugging Face Spaces, webcam access is not supported. Try running this app locally for webcam features.")1095                        st.session_state.feature_camera_running = False1096                    else:1097                        # Display real-time video with face and feature detection1098                        try:1099                            # Create placeholders for metrics1100                            metrics_placeholder = st.empty()1101                            metrics_col1, metrics_col2, metrics_col3 = metrics_placeholder.columns(3)1102                            1103                            # Initialize counters1104                            face_count_total = 01105                            eye_count_total = 01106                            smile_count_total = 01107                            frame_count = 01108                            1109                            while st.session_state.feature_camera_running:1110                                ret, frame = cap.read()1111                                if not ret:1112                                    st.error("Error reading frame from camera.")1113                                    break1114                                1115                                # Detect faces1116                                detections = detect_face_dnn(face_net, frame, conf_threshold)1117                                processed_frame, bboxes = process_face_detections(frame, detections, conf_threshold, bbox_color_bgr)1118                                1119                                # Update face counter1120                                face_count = len(bboxes)1121                                face_count_total += face_count1122                                1123                                # Initialize counters for this frame1124                                eye_count = 01125                                smile_count = 01126                                1127                                # Detect facial features if enabled1128                                if detect_eyes or detect_smile:1129                                    processed_frame, eye_count, smile_count = detect_facial_features(1130                                        processed_frame, 1131                                        bboxes,1132                                        eye_cascade,1133                                        smile_cascade,1134                                        detect_eyes,1135                                        detect_smile,1136                                        smile_sensitivity,1137                                        eye_sensitivity1138                                    )1139                                    1140                                    # Update total counters1141                                    eye_count_total += eye_count1142                                    smile_count_total += smile_count1143                                1144                                # Apply age/gender detection if enabled1145                                if detect_age_gender_option:1146                                    processed_frame = detect_age_gender(processed_frame, bboxes)1147                                1148                                # Display the processed frame1149                                camera_placeholder.image(processed_frame, channels="BGR", use_container_width=True)1150                                1151                                # Update frame counter1152                                frame_count += 11153                                1154                                # Update metrics every 5 frames to avoid overloading the interface1155                                if frame_count % 5 == 0:1156                                    metrics_col1.metric("Faces Detected", face_count)1157                                    1158                                    if detect_eyes:1159                                        metrics_col2.metric("Eyes Detected", eye_count)1160                                    else:1161                                        metrics_col2.metric("Eyes Detected", "N/A")1162                                    1163                                    if detect_smile:1164                                        metrics_col3.metric("Smiles Detected", smile_count)1165                                    else:1166                                        metrics_col3.metric("Smiles Detected", "N/A")1167                                1168                                # Small pause to avoid overloading the CPU1169                                time.sleep(0.01)1170                        finally:1171                            # Release the camera when stopped1172                            cap.release()1173 1174    elif app_mode == "Comparison Mode":1175        st.subheader("Face Comparison")1176        st.write("Upload two images to compare faces between them.")1177        1178        # Añadir explicación sobre la interpretación de resultados1179        with st.expander("📌 How to interpret similarity results"):1180            st.markdown("""1181            ### Facial Similarity Interpretation Guide1182            1183            The system calculates similarity between faces based on multiple facial features and characteristics.1184            1185            **Similarity Ranges:**1186            - **70-100%**: HIGH Similarity - Very likely to be the same person or identical twins1187            - **50-70%**: MEDIUM Similarity - Possible match, requires verification1188            - **30-50%**: LOW Similarity - Different people with some similar features1189            - **0-30%**: VERY LOW Similarity - Completely different people1190            1191            **Enhanced Comparison System:**1192            The system uses a sophisticated approach that:1193            1. Analyzes multiple facial characteristics with advanced precision1194            2. Evaluates hair style/color, facial structure, texture patterns, and expressions with improved accuracy1195            3. Applies a balanced differentiation between similar and different individuals1196            4. Creates a clear gap between similar and different people's scores1197            5. Reduces scores for people with different facial structures1198            6. Applies penalty factors for critical differences in facial features1199            1200            **Features Analyzed:**

Showing the first 1,200 of 2501 lines. Download the file for the rest.