Team Ai
Apppublic

jarondon82/ComputerVisionProject

sourceHugging Faceupdated 2y agoView on Hugging Face
1likes
streamlit_app_corrected.py2143 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 pd15 16# Importar DeepFace para reconocimiento facial avanzado17try:18    from deepface import DeepFace19    DEEPFACE_AVAILABLE = True20except ImportError:21    DEEPFACE_AVAILABLE = False22 23# Import functions for face comparison24try:25    from face_comparison import compare_faces, compare_faces_embeddings, generate_comparison_report_english, draw_face_matches, extract_face_embeddings, extract_face_embeddings_all_models26    FACE_COMPARISON_AVAILABLE = True27except ImportError:28    FACE_COMPARISON_AVAILABLE = False29    st.warning("Face comparison functions are not available. Please check your installation.")30 31# Funci贸n principal que encapsula toda la aplicaci贸n32def main():33    # Set page config with custom title and layout34    st.set_page_config(35        page_title="Advanced Face & Feature Detection",36        page_icon="馃懁",37        layout="wide",38        initial_sidebar_state="expanded"39    )40    41    # Sidebar for navigation and controls42    st.sidebar.title("Controls & Settings")43 44    # Initialize session_state to store original image and camera state45    if 'original_image' not in st.session_state:46        st.session_state.original_image = None47    if 'camera_running' not in st.session_state:48        st.session_state.camera_running = False49    if 'feature_camera_running' not in st.session_state:50        st.session_state.feature_camera_running = False51 52    # Navigation menu53    app_mode = st.sidebar.selectbox(54        "Choose the app mode",55        ["About", "Face Detection", "Feature Detection", "Comparison Mode", "Face Recognition"]56    )57 58    # Function to load DNN models with caching and auto-download59    @st.cache_resource60    def load_face_model():61        # No need to create directory as we're using the root directory62        #63            #64        65        # Correct model file names66        modelFile = "res10_300x300_ssd_iter_140000.caffemodel"67        configFile = "deploy.prototxt.txt"68        69        # Check if files exist70        missing_files = []71        if not os.path.exists(modelFile):72            missing_files.append(modelFile)73        if not os.path.exists(configFile):74            missing_files.append(configFile)75        76        if missing_files:77            st.error("Missing model files: " + ", ".join(missing_files))78            st.error("Please manually download the following files:")79            st.code("""80            1. Download the model file:81               URL: https://raw.githubusercontent.com/sr6033/face-detection-with-OpenCV-and-DNN/master/res10_300x300_ssd_iter_140000.caffemodel82               Save as: res10_300x300_ssd_iter_140000.caffemodel83               84            2. Download the configuration file:85               URL: https://raw.githubusercontent.com/sr6033/face-detection-with-OpenCV-and-DNN/master/deploy.prototxt.txt86               Save as: deploy.prototxt.txt87            """)88            st.stop()89        90        # Load model91        try:92            net = cv2.dnn.readNetFromCaffe(configFile, modelFile)93            return net94        except Exception as e:95            st.error(f"Error loading model: {e}")96            st.stop()97 98    @st.cache_resource99    def load_feature_models():100        # Load pre-trained models for eye and smile detection101        eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye.xml')102        smile_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_smile.xml')103        return eye_cascade, smile_cascade104 105    # Function for detecting faces in an image106    def detect_face_dnn(net, frame, conf_threshold=0.5):107        blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), [104, 117, 123], False, False)108        net.setInput(blob)109        detections = net.forward()110        111        # Procesar las detecciones para devolver una lista de bounding boxes112        bboxes = []113        frame_h = frame.shape[0]114        frame_w = frame.shape[1]115        116        for i in range(detections.shape[2]):117            confidence = detections[0, 0, i, 2]118            if confidence > conf_threshold:119                x1 = int(detections[0, 0, i, 3] * frame_w)120                y1 = int(detections[0, 0, i, 4] * frame_h)121                x2 = int(detections[0, 0, i, 5] * frame_w)122                y2 = int(detections[0, 0, i, 6] * frame_h)123                124                # Asegurarse de que las coordenadas est茅n dentro de los l铆mites de la imagen125                x1 = max(0, min(x1, frame_w - 1))126                y1 = max(0, min(y1, frame_h - 1))127                x2 = max(0, min(x2, frame_w - 1))128                y2 = max(0, min(y2, frame_h - 1))129                130                # A帽adir el bounding box y la confianza131                bboxes.append([x1, y1, x2, y2, confidence])132        133        return bboxes134 135    # Function for processing face detections136    def process_face_detections(frame, detections, conf_threshold=0.5, bbox_color=(0, 255, 0)):137        # Create a copy for drawing on138        result_frame = frame.copy()139        140        # Filtrar detecciones por umbral de confianza141        bboxes = []142        for detection in detections:143            if len(detection) == 5:  # Asegurarse de que la detecci贸n tiene el formato correcto144                x1, y1, x2, y2, confidence = detection145                if confidence >= conf_threshold:146                    # Dibujar el bounding box147                    cv2.rectangle(result_frame, (x1, y1), (x2, y2), bbox_color, 2)148                    149                    # A帽adir texto con la confianza150                    label = f"{confidence:.2f}"151                    cv2.putText(result_frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, bbox_color, 2)152                    153                    # A帽adir a la lista de bounding boxes154                    bboxes.append([x1, y1, x2, y2, confidence])155        156        return result_frame, bboxes157 158    # Function to detect facial features (eyes, smile) with improved profile face handling159    def detect_facial_features(frame, bboxes, eye_cascade, smile_cascade, detect_eyes=True, detect_smile=True, smile_sensitivity=15, eye_sensitivity=5):160        result_frame = frame.copy()161        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)162        163        # Counters for detection summary164        eye_count = 0165        smile_count = 0166        167        for bbox in bboxes:168            x1, y1, x2, y2, _ = bbox169            roi_gray = gray[y1:y2, x1:x2]170            roi_color = result_frame[y1:y2, x1:x2]171            face_width = x2 - x1172            face_height = y2 - y1173            174            # Detect eyes if enabled175            if detect_eyes:176                # Adjust region of interest to focus on the upper part of the face177                upper_face_y1 = y1178                upper_face_y2 = y1 + int(face_height * 0.55)  # Slightly reduced to focus more on the eye area179                180                # For profile faces, we need to search the entire upper region181                # as well as the left and right sides separately182                183                # Full upper region for profile faces184                upper_face_roi_gray = gray[upper_face_y1:upper_face_y2, x1:x2]185                upper_face_roi_color = result_frame[upper_face_y1:upper_face_y2, x1:x2]186                187                # Split the upper region into two halves (left and right) to search for eyes individually188                mid_x = x1 + face_width // 2189                left_eye_roi_gray = gray[upper_face_y1:upper_face_y2, x1:mid_x]190                right_eye_roi_gray = gray[upper_face_y1:upper_face_y2, mid_x:x2]191                192                left_eye_roi_color = result_frame[upper_face_y1:upper_face_y2, x1:mid_x]193                right_eye_roi_color = result_frame[upper_face_y1:upper_face_y2, mid_x:x2]194                195                # Apply histogram equalization and contrast enhancement for all regions196                if upper_face_roi_gray.size > 0:197                    upper_face_roi_gray = cv2.equalizeHist(upper_face_roi_gray)198                    199                    # Enhance contrast200                    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))201                    upper_face_roi_gray = clahe.apply(upper_face_roi_gray)202                    203                    # First try to detect eyes in the full upper region (for profile faces)204                    full_eyes = eye_cascade.detectMultiScale(205                        upper_face_roi_gray, 206                        scaleFactor=1.02,  # More sensitive for profile faces207                        minNeighbors=max(1, eye_sensitivity-3),  # Even more sensitive208                        minSize=(int(face_width * 0.07), int(face_width * 0.07)),209                        maxSize=(int(face_width * 0.3), int(face_width * 0.3))210                    )211                    212                    # If we found eyes in the full region, use those213                    if len(full_eyes) > 0:214                        # Sort by size (area) and take up to 2 largest215                        full_eyes = sorted(full_eyes, key=lambda e: e[2] * e[3], reverse=True)216                        full_eyes = full_eyes[:2]  # Take at most 2 eyes217                        218                        for ex, ey, ew, eh in full_eyes:219                            eye_count += 1220                            cv2.rectangle(upper_face_roi_color, (ex, ey), (ex+ew, ey+eh), (255, 0, 0), 2)221                            cv2.putText(upper_face_roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)222                    else:223                        # If no eyes found in full region, try left and right separately224                        if left_eye_roi_gray.size > 0:225                            left_eye_roi_gray = cv2.equalizeHist(left_eye_roi_gray)226                            left_eye_roi_gray = clahe.apply(left_eye_roi_gray)227                            228                            left_eyes = eye_cascade.detectMultiScale(229                                left_eye_roi_gray, 230                                scaleFactor=1.03,231                                minNeighbors=max(1, eye_sensitivity-2),232                                minSize=(int(face_width * 0.08), int(face_width * 0.08)),233                                maxSize=(int(face_width * 0.25), int(face_width * 0.25))234                            )235                            236                            if len(left_eyes) > 0:237                                # Sort by size and take the largest238                                left_eyes = sorted(left_eyes, key=lambda e: e[2] * e[3], reverse=True)239                                left_eye = left_eyes[0]240                                eye_count += 1241                                242                                # Draw rectangle for the left eye243                                ex, ey, ew, eh = left_eye244                                cv2.rectangle(left_eye_roi_color, (ex, ey), (ex+ew, ey+eh), (255, 0, 0), 2)245                                cv2.putText(left_eye_roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)246                        247                        if right_eye_roi_gray.size > 0:248                            right_eye_roi_gray = cv2.equalizeHist(right_eye_roi_gray)249                            right_eye_roi_gray = clahe.apply(right_eye_roi_gray)250                            251                            right_eyes = eye_cascade.detectMultiScale(252                                right_eye_roi_gray, 253                                scaleFactor=1.03,254                                minNeighbors=max(1, eye_sensitivity-2),255                                minSize=(int(face_width * 0.08), int(face_width * 0.08)),256                                maxSize=(int(face_width * 0.25), int(face_width * 0.25))257                            )258                            259                            if len(right_eyes) > 0:260                                # Sort by size and take the largest261                                right_eyes = sorted(right_eyes, key=lambda e: e[2] * e[3], reverse=True)262                                right_eye = right_eyes[0]263                                eye_count += 1264                                265                                # Draw rectangle for the right eye266                                ex, ey, ew, eh = right_eye267                                cv2.rectangle(right_eye_roi_color, (ex, ey), (ex+ew, ey+eh), (255, 0, 0), 2)268                                cv2.putText(right_eye_roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)269            270            # Detect smile if enabled271            if detect_smile:272                # For profile faces, we need to adjust the region of interest273                # Try multiple regions to improve detection274                275                # Standard region (middle to bottom)276                lower_face_y1 = y1 + int(face_height * 0.5)277                lower_face_roi_gray = gray[lower_face_y1:y2, x1:x2]278                lower_face_roi_color = result_frame[lower_face_y1:y2, x1:x2]279                280                # Alternative region (lower third)281                alt_lower_face_y1 = y1 + int(face_height * 0.65)282                alt_lower_face_roi_gray = gray[alt_lower_face_y1:y2, x1:x2]283                284                # Apply histogram equalization and enhance contrast285                smile_detected = False286                287                if lower_face_roi_gray.size > 0:288                    lower_face_roi_gray = cv2.equalizeHist(lower_face_roi_gray)289                    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))290                    lower_face_roi_gray = clahe.apply(lower_face_roi_gray)291                    292                    # Try with standard parameters293                    smiles = smile_cascade.detectMultiScale(294                        lower_face_roi_gray, 295                        scaleFactor=1.2,296                        minNeighbors=smile_sensitivity,297                        minSize=(int(face_width * 0.25), int(face_width * 0.15)),298                        maxSize=(int(face_width * 0.7), int(face_width * 0.4))299                    )300                    301                    if len(smiles) > 0:302                        # Sort by size and take the largest303                        smiles = sorted(smiles, key=lambda s: s[2] * s[3], reverse=True)304                        sx, sy, sw, sh = smiles[0]305                        306                        # Increment smile counter307                        smile_count += 1308                        smile_detected = True309                        310                        # Draw rectangle for the smile311                        cv2.rectangle(lower_face_roi_color, (sx, sy), (sx+sw, sy+sh), (0, 0, 255), 2)312                        cv2.putText(lower_face_roi_color, "Smile", (sx, sy-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)313                314                # If no smile detected in standard region, try alternative region315                if not smile_detected and alt_lower_face_roi_gray.size > 0:316                    alt_lower_face_roi_gray = cv2.equalizeHist(alt_lower_face_roi_gray)317                    alt_lower_face_roi_gray = clahe.apply(alt_lower_face_roi_gray)318                    319                    # Try with more sensitive parameters320                    alt_smiles = smile_cascade.detectMultiScale(321                        alt_lower_face_roi_gray, 322                        scaleFactor=1.1,323                        minNeighbors=max(1, smile_sensitivity-5),  # More sensitive324                        minSize=(int(face_width * 0.2), int(face_width * 0.1)),325                        maxSize=(int(face_width * 0.6), int(face_width * 0.3))326                    )327                    328                    if len(alt_smiles) > 0:329                        # Sort by size and take the largest330                        alt_smiles = sorted(alt_smiles, key=lambda s: s[2] * s[3], reverse=True)331                        sx, sy, sw, sh = alt_smiles[0]332                        333                        # Adjust coordinates for the alternative region334                        adjusted_sy = sy + (alt_lower_face_y1 - lower_face_y1)335                        336                        # Increment smile counter337                        smile_count += 1338                        339                        # Draw rectangle for the smile (in the original lower face ROI)340                        cv2.rectangle(lower_face_roi_color, (sx, adjusted_sy), (sx+sw, adjusted_sy+sh), (0, 0, 255), 2)341                        cv2.putText(lower_face_roi_color, "Smile", (sx, adjusted_sy-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)342        343        return result_frame, eye_count, smile_count344 345    # Funci贸n para detectar atributos faciales (edad, g茅nero, emoci贸n)346    def detect_face_attributes(image, bbox):347        """348        Detecta atributos faciales como edad, g茅nero y emoci贸n usando DeepFace.349        350        Args:351            image: Imagen en formato OpenCV (BGR)352            bbox: Bounding box de la cara [x1, y1, x2, y2, conf]353            354        Returns:355            Diccionario con los atributos detectados356        """357        if not DEEPFACE_AVAILABLE:358            return None359        360        try:361            x1, y1, x2, y2, _ = bbox362            face_img = image[y1:y2, x1:x2]363            364            # Convertir de BGR a RGB para DeepFace365            face_img_rgb = cv2.cvtColor(face_img, cv2.COLOR_BGR2RGB)366            367            # Analyze atributos faciales368            attributes = DeepFace.analyze(369                img_path=face_img_rgb,370                actions=['age', 'gender', 'emotion'],371                enforce_detection=False,372                detector_backend="opencv"373            )374            375            return attributes[0]376        377        except Exception as e:378            st.error(f"Error detecting facial attributes: {str(e)}")379            return None380 381    # Function to apply age and gender detection (placeholder - would need additional models)382    def detect_age_gender(frame, bboxes):383        # Versi贸n mejorada que usa DeepFace si est谩 disponible384        result_frame = frame.copy()385        386        for i, bbox in enumerate(bboxes):387            x1, y1, x2, y2, _ = bbox388            389            if DEEPFACE_AVAILABLE:390                # Intentar usar DeepFace para an谩lisis facial391                attributes = detect_face_attributes(frame, bbox)392                393                if attributes:394                    # Extraer informaci贸n de atributos395                    age = attributes.get('age', 'Unknown')396                    gender = attributes.get('gender', 'Unknown')397                    emotion = attributes.get('dominant_emotion', 'Unknown').capitalize()398                    gender_prob = attributes.get('gender', {}).get('Woman', 0)399                    400                    # Determinar color basado en confianza401                    if gender == 'Woman':402                        gender_color = (255, 0, 255)  # Magenta para mujer403                    else:404                        gender_color = (255, 0, 0)    # Azul para hombre405                    406                    # A帽adir texto con informaci贸n407                    cv2.putText(result_frame, f"Age: {age}", (x1, y2+20), 408                               cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2)409                    cv2.putText(result_frame, f"Gender: {gender}", (x1, y2+40), 410                               cv2.FONT_HERSHEY_SIMPLEX, 0.5, gender_color, 2)411                    cv2.putText(result_frame, f"Emotion: {emotion}", (x1, y2+60), 412                               cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 255), 2)413                else:414                    # Fallback si DeepFace falla415                    cv2.putText(result_frame, "Age: Unknown", (x1, y2+20), 416                               cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 2)417                    cv2.putText(result_frame, "Gender: Unknown", (x1, y2+40), 418                               cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 2)419            else:420                # Usar texto placeholder si DeepFace no est谩 disponible421                cv2.putText(result_frame, "Age: 25-35", (x1, y2+20), 422                           cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 2)423                cv2.putText(result_frame, "Gender: Unknown", (x1, y2+40), 424                           cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 2)425        426        return result_frame427 428    # Function to generate download link for processed image429    def get_image_download_link(img, filename, text):430        buffered = BytesIO()431        img.save(buffered, format="JPEG")432        img_str = base64.b64encode(buffered.getvalue()).decode()433        href = f'<a href="data:file/txt;base64,{img_str}" download="{filename}">{text}</a>'434        return href435 436    # Function to process video frames437    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):438        cap = cv2.VideoCapture(video_path)439        440        # Get video properties441        frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))442        frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))443        fps = int(cap.get(cv2.CAP_PROP_FPS))444        445        # Create temporary output file446        temp_dir = tempfile.mkdtemp()447        temp_output_path = os.path.join(temp_dir, "processed_video.mp4")448        449        # Initialize video writer450        fourcc = cv2.VideoWriter_fourcc(*'mp4v')451        out = cv2.VideoWriter(temp_output_path, fourcc, fps, (frame_width, frame_height))452        453        # Create a progress bar454        frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))455        progress_bar = st.progress(0)456        status_text = st.empty()457        458        # Process video frames459        current_frame = 0460        processing_times = []461        462        # Total counters for statistics463        total_faces = 0464        total_eyes = 0465        total_smiles = 0466        467        while cap.isOpened():468            ret, frame = cap.read()469            if not ret:470                break471            472            # Start timing for performance metrics473            start_time = time.time()474            475            # Detect faces476            detections = detect_face_dnn(face_net, frame, conf_threshold)477            processed_frame, bboxes = process_face_detections(frame, detections, conf_threshold, bbox_color)478            479            # Update face counter480            total_faces += len(bboxes)481            482            # Detect facial features if enabled483            if detect_eyes or detect_smile:484                processed_frame, eye_count, smile_count = detect_facial_features(485                    processed_frame, 486                    bboxes, 487                    eye_cascade, 488                    smile_cascade,489                    detect_eyes,490                    detect_smile,491                    smile_sensitivity,492                    eye_sensitivity493                )494                # Update counters495                total_eyes += eye_count496                total_smiles += smile_count497            498            # End timing499            processing_times.append(time.time() - start_time)500            501            # Write the processed frame502            out.write(processed_frame)503            504            # Update progress505            current_frame += 1506            progress_bar.progress(current_frame / frame_count)507            status_text.text(f"Processing frame {current_frame}/{frame_count}")508        509        # Release resources510        cap.release()511        out.release()512        513        # Calculate and display performance metrics514        if processing_times:515            avg_time = sum(processing_times) / len(processing_times)516            status_text.text(f"Processing complete! Average processing time: {avg_time:.4f}s per frame")517        518        # Return detection statistics519        detection_stats = {520            "faces": total_faces // max(1, current_frame),  # Average per frame521            "eyes": total_eyes // max(1, current_frame),    # Average per frame522            "smiles": total_smiles // max(1, current_frame) # Average per frame523        }524        525        return temp_output_path, temp_dir, detection_stats526 527    # Camera control functions528    def start_camera():529        st.session_state.camera_running = True530 531    def stop_camera():532        st.session_state.camera_running = False533        st.session_state.camera_stopped = True534 535    def start_feature_camera():536        st.session_state.feature_camera_running = True537 538    def stop_feature_camera():539        st.session_state.feature_camera_running = False540        st.session_state.feature_camera_stopped = True541 542    if app_mode == "About":543        st.markdown("""544        ## About This App545        546        This application uses OpenCV's Deep Neural Network (DNN) module and Haar Cascade classifiers to detect faces and facial features in images and videos.547        548        ### Features:549        - Face detection using OpenCV DNN550        - Eye and smile detection using Haar Cascades551        - Support for both image and video processing552        - Adjustable confidence threshold553        - Download options for processed media554        - Performance metrics555        556        ### How to use:557        1. Select a mode from the sidebar558        2. Upload an image or video559        3. Adjust settings as needed560        4. View and download the results561        562        ### Technologies Used:563        - Streamlit for the web interface564        - OpenCV for computer vision operations565        - Python for backend processing566        567        ### Models:568        - SSD MobileNet for face detection569        - Haar Cascades for facial features570        """)571        572        # Display a sample image or GIF573        st.image("https://opencv.org/wp-content/uploads/2019/07/detection.gif", caption="Sample face detection", use_container_width=True)574 575    elif app_mode == "Face Detection":576        # Load the face detection model577        face_net = load_face_model()578        579        # Input type selection (Image or Video)580        input_type = st.sidebar.radio("Select Input Type", ["Image", "Video"])581        582        # Confidence threshold slider583        conf_threshold = st.sidebar.slider(584            "Confidence Threshold", 585            min_value=0.0, 586            max_value=1.0, 587            value=0.5, 588            step=0.05,589            help="Adjust the threshold for face detection confidence (higher = fewer detections but more accurate)"590        )591        592        # Style options593        bbox_color = st.sidebar.color_picker("Bounding Box Color", "#00FF00")594        # Convert hex color to BGR for OpenCV595        bbox_color_rgb = tuple(int(bbox_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))596        bbox_color_bgr = (bbox_color_rgb[2], bbox_color_rgb[1], bbox_color_rgb[0])  # Convert RGB to BGR597        598        # Display processing metrics599        show_metrics = st.sidebar.checkbox("Show Processing Metrics", True)600        601        if input_type == "Image":602            # File uploader for images603            file_buffer = st.file_uploader("Upload an image", type=['jpg', 'jpeg', 'png'])604            605            if file_buffer is not None:606                # Read the file and convert it to OpenCV format607                raw_bytes = np.asarray(bytearray(file_buffer.read()), dtype=np.uint8)608                image = cv2.imdecode(raw_bytes, cv2.IMREAD_COLOR)609                610                # Save la imagen original en session_state para reprocesarla cuando cambie el umbral611                # Usar un identificador 煤nico para cada archivo para detectar cambios612                file_id = file_buffer.name + str(file_buffer.size)613                614                if 'file_id' not in st.session_state or st.session_state.file_id != file_id:615                    st.session_state.file_id = file_id616                    st.session_state.original_image = image.copy()617                618                # Display original image619                col1, col2 = st.columns(2)620                with col1:621                    st.subheader("Original Image")622                    st.image(st.session_state.original_image, channels='BGR', use_container_width=True)623                624                # Start timing for performance metrics625                start_time = time.time()626                627                # Detect faces628                detections = detect_face_dnn(face_net, st.session_state.original_image, conf_threshold)629                processed_image, bboxes = process_face_detections(st.session_state.original_image, detections, conf_threshold, bbox_color_bgr)630                631                # Calculate processing time632                processing_time = time.time() - start_time633                634                # Display the processed image635                with col2:636                    st.subheader("Processed Image")637                    st.image(processed_image, channels='BGR', use_container_width=True)638                    639                    # Convert OpenCV image to PIL for download640                    pil_img = Image.fromarray(processed_image[:, :, ::-1])641                    st.markdown(642                        get_image_download_link(pil_img, "face_detection_result.jpg", "馃摜 Download Processed Image"),643                        unsafe_allow_html=True644                    )645                646                # Show metrics if enabled647                if show_metrics:648                    st.subheader("Processing Metrics")649                    col1, col2, col3 = st.columns(3)650                    col1.metric("Processing Time", f"{processing_time:.4f} seconds")651                    col2.metric("Faces Detected", len(bboxes))652                    col3.metric("Confidence Threshold", f"{conf_threshold:.2f}")653                    654                    # Display detailed metrics in an expandable section655                    with st.expander("Detailed Detection Information"):656                        if bboxes:657                            st.write("Detected faces with confidence scores:")658                            for i, bbox in enumerate(bboxes):659                                st.write(f"Face #{i+1}: Confidence = {bbox[4]:.4f}")660                        else:661                            st.write("No faces detected in the image.")662        663        else:  # Video mode664            # Video mode options665            video_source = st.radio("Select video source", ["Upload video", "Use webcam"])666            667            if video_source == "Upload video":668                # File uploader for videos669                file_buffer = st.file_uploader("Upload a video", type=['mp4', 'avi', 'mov'])670                671                if file_buffer is not None:672                    # Save uploaded video to temporary file673                    temp_dir = tempfile.mkdtemp()674                    temp_path = os.path.join(temp_dir, "input_video.mp4")675                    676                    with open(temp_path, "wb") as f:677                        f.write(file_buffer.read())678                    679                    # Display original video680                    st.subheader("Original Video")681                    st.video(temp_path)682                    683                    # Load models for feature detection (will be used in the processing)684                    eye_cascade, smile_cascade = load_feature_models()685                    686                    # Process video button687                    if st.button("Process Video"):688                        with st.spinner("Processing video... This may take a while depending on the video length."):689                            # Process the video690                            output_path, output_dir, detection_stats = process_video(691                                temp_path, 692                                face_net, 693                                eye_cascade,694                                smile_cascade,695                                conf_threshold,696                                detect_eyes=True,697                                detect_smile=True,698                                bbox_color=bbox_color_bgr,699                                eye_sensitivity=5700                            )701                            702                            # Display processed video703                            st.subheader("Processed Video")704                            st.video(output_path)705                            706                            # Mostrar estad铆sticas de detecci贸n707                            st.subheader("Detection Summary")708                            summary_col1, summary_col2, summary_col3 = st.columns(3)709                            summary_col1.metric("Avg. Faces per Frame", detection_stats["faces"])710                            711                            if detect_eyes: # type: ignore712                                summary_col2.metric("Avg. Eyes per Frame", detection_stats["eyes"])713                            else:714                                summary_col2.metric("Eyes Detected", "N/A")715                            716                            if detect_smile: # type: ignore717                                summary_col3.metric("Avg. Smiles per Frame", detection_stats["smiles"])718                            else:719                                summary_col3.metric("Smiles Detected", "N/A")720                            721                            # Provide download link722                            with open(output_path, 'rb') as f:723                                video_bytes = f.read()724                            725                            st.download_button(726                                label="馃摜 Download Processed Video",727                                data=video_bytes,728                                file_name="processed_video.mp4",729                                mime="video/mp4"730                            )731                            732                            # Clean up temporary files733                            try:734                                os.remove(temp_path)735                                os.remove(output_path)736                                os.rmdir(temp_dir)737                                os.rmdir(output_dir)738                            except:739                                pass740            else:  # Use webcam741                st.subheader("Real-time face detection")742                st.write("Click 'Start Camera' to begin real-time face detection.")743                744                # Placeholder for webcam video745                camera_placeholder = st.empty()746                747                # Buttons to control the camera748                col1, col2 = st.columns(2)749                start_button = col1.button("Start Camera", on_click=start_camera)750                stop_button = col2.button("Stop Camera", on_click=stop_camera)751                752                # Show message when camera is stopped753                if 'camera_stopped' in st.session_state and st.session_state.camera_stopped:754                    st.info("Camera stopped. Click 'Start Camera' to activate it again.")755                    st.session_state.camera_stopped = False756                757                if st.session_state.camera_running:758                    st.info("Camera activated. Processing real-time video...")759                    # Initialize webcam760                    cap = cv2.VideoCapture(0)  # 0 is typically the main webcam761                    762                    if not cap.isOpened():763                        st.error("Could not access webcam. Make sure it's connected and not being used by another application.")764                        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.")765                        st.session_state.camera_running = False766                    else:767                        # Display real-time video with face detection768                        try:769                            while st.session_state.camera_running:770                                ret, frame = cap.read()771                                if not ret:772                                    st.error("Error reading frame from camera.")773                                    break774                                775                                # Detect faces776                                detections = detect_face_dnn(face_net, frame, conf_threshold)777                                processed_frame, bboxes = process_face_detections(frame, detections, conf_threshold, bbox_color_bgr)778                                779                                # Display the processed frame780                                camera_placeholder.image(processed_frame, channels="BGR", use_container_width=True)781                                782                                # Small pause to avoid overloading the CPU783                                time.sleep(0.01)784                        finally:785                            # Release the camera when stopped786                            cap.release()787 788    elif app_mode == "Feature Detection":789        # Load all required models790        face_net = load_face_model()791        eye_cascade, smile_cascade = load_feature_models()792        793        # Feature selection checkboxes794        st.sidebar.subheader("Feature Detection Options")795        detect_eyes = st.sidebar.checkbox("Detect Eyes", True)796        797        # Add controls for eye detection sensitivity798        eye_sensitivity = 5  # Default value799        if detect_eyes:800            eye_sensitivity = st.sidebar.slider(801                "Eye Detection Sensitivity", 802                min_value=1, 803                max_value=10, 804                value=5, 805                step=1,806                help="Adjust the sensitivity of eye detection (lower value = more detections)"807            )808        809        detect_smile = st.sidebar.checkbox("Detect Smile", True)810        811        # Add controls for smile detection sensitivity812        smile_sensitivity = 15  # Default value813        if detect_smile:814            smile_sensitivity = st.sidebar.slider(815                "Smile Detection Sensitivity", 816                min_value=5, 817                max_value=30, 818                value=15, 819                step=1,820                help="Adjust the sensitivity of smile detection (lower value = more detections)"821            )822        823        detect_age_gender_option = st.sidebar.checkbox("Detect Age/Gender (Demo)", False)824        825        # Confidence threshold slider826        conf_threshold = st.sidebar.slider(827            "Face Detection Confidence", 828            min_value=0.0, 829            max_value=1.0, 830            value=0.5, 831            step=0.05832        )833        834        # Style options835        bbox_color = st.sidebar.color_picker("Bounding Box Color", "#00FF00")836        # Convert hex color to BGR for OpenCV837        bbox_color_rgb = tuple(int(bbox_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))838        bbox_color_bgr = (bbox_color_rgb[2], bbox_color_rgb[1], bbox_color_rgb[0])  # Convert RGB to BGR839        840        # Input type selection841        input_type = st.sidebar.radio("Select Input Type", ["Image", "Video"])842        843        if input_type == "Image":844            # File uploader for images845            file_buffer = st.file_uploader("Upload an image", type=['jpg', 'jpeg', 'png'])846            847            if file_buffer is not None:848                # Read the file and convert it to OpenCV format849                raw_bytes = np.asarray(bytearray(file_buffer.read()), dtype=np.uint8)850                image = cv2.imdecode(raw_bytes, cv2.IMREAD_COLOR)851                852                # Save la imagen original en session_state para reprocesarla cuando cambie el umbral853                # Usar un identificador 煤nico para cada archivo para detectar cambios854                file_id = file_buffer.name + str(file_buffer.size)855                856                if 'feature_file_id' not in st.session_state or st.session_state.feature_file_id != file_id:857                    st.session_state.feature_file_id = file_id858                    st.session_state.feature_original_image = image.copy()859                860                # Display original image861                col1, col2 = st.columns(2)862                with col1:863                    st.subheader("Original Image")864                    st.image(st.session_state.feature_original_image, channels='BGR', use_container_width=True)865                866                # Start processing with face detection867                detections = detect_face_dnn(face_net, st.session_state.feature_original_image, conf_threshold)868                processed_image, bboxes = process_face_detections(st.session_state.feature_original_image, detections, conf_threshold, bbox_color_bgr)869                870                # Inicializar contadores871                eye_count = 0872                smile_count = 0873                874                # Detect facial features if any options are enabled875                if detect_eyes or detect_smile:876                    processed_image, eye_count, smile_count = detect_facial_features(877                        processed_image, 878                        bboxes,879                        eye_cascade,880                        smile_cascade,881                        detect_eyes,882                        detect_smile,883                        smile_sensitivity,884                        eye_sensitivity885                    )886                    887                # Apply age/gender detection if enabled (demo purpose)888                if detect_age_gender_option:889                    processed_image = detect_age_gender(processed_image, bboxes)890                891                # Display the processed image892                with col2:893                    st.subheader("Processed Image")894                    st.image(processed_image, channels='BGR', use_container_width=True)895                    896                    # Convert OpenCV image to PIL for download897                    pil_img = Image.fromarray(processed_image[:, :, ::-1])898                    st.markdown(899                        get_image_download_link(pil_img, "feature_detection_result.jpg", "馃摜 Download Processed Image"),900                        unsafe_allow_html=True901                    )902                903                # Display detection summary904                st.subheader("Detection Summary")905                summary_col1, summary_col2, summary_col3 = st.columns(3)906                summary_col1.metric("Faces Detected", len(bboxes))907                908                if detect_eyes:909                    summary_col2.metric("Eyes Detected", eye_count)910                else:911                    summary_col2.metric("Eyes Detected", "N/A")912                913                if detect_smile:914                    summary_col3.metric("Smiles Detected", smile_count)915                else:916                    summary_col3.metric("Smiles Detected", "N/A")917        918        else:  # Video mode919            st.write("Facial feature detection in video")920            921            # Video mode options922            video_source = st.radio("Select video source", ["Upload video", "Use webcam"])923            924            if video_source == "Upload video":925                st.write("Upload a video to process with facial feature detection.")926                # Similar implementation to Face Detection mode for uploaded videos927                file_buffer = st.file_uploader("Upload a video", type=['mp4', 'avi', 'mov'])928                929                if file_buffer is not None:930                    # Save uploaded video to temporary file931                    temp_dir = tempfile.mkdtemp()932                    temp_path = os.path.join(temp_dir, "input_video.mp4")933                    934                    with open(temp_path, "wb") as f:935                        f.write(file_buffer.read())936                    937                    # Display original video938                    st.subheader("Original Video")939                    st.video(temp_path)940                    941                    # Process video button942                    if st.button("Process Video"):943                        with st.spinner("Processing video... This may take a while depending on the video length."):944                            # Process the video with feature detection945                            output_path, output_dir, detection_stats = process_video(946                                temp_path, 947                                face_net, 948                                eye_cascade,949                                smile_cascade,950                                conf_threshold,951                                detect_eyes=True,952                                detect_smile=True,953                                bbox_color=bbox_color_bgr,954                                smile_sensitivity=smile_sensitivity,955                                eye_sensitivity=eye_sensitivity956                            )957                            958                            # Display processed video959                            st.subheader("Processed Video")960                            st.video(output_path)961                            962                            # Mostrar estad铆sticas de detecci贸n963                            st.subheader("Detection Summary")964                            summary_col1, summary_col2, summary_col3 = st.columns(3)965                            summary_col1.metric("Avg. Faces per Frame", detection_stats["faces"])966                            967                            if detect_eyes:968                                summary_col2.metric("Avg. Eyes per Frame", detection_stats["eyes"])969                            else:970                                summary_col2.metric("Eyes Detected", "N/A")971                            972                            if detect_smile:973                                summary_col3.metric("Avg. Smiles per Frame", detection_stats["smiles"])974                            else:975                                summary_col3.metric("Smiles Detected", "N/A")976                            977                            # Provide download link978                            with open(output_path, 'rb') as f:979                                video_bytes = f.read()980                            981                            st.download_button(982                                label="馃摜 Download Processed Video",983                                data=video_bytes,984                                file_name="feature_detection_video.mp4",985                                mime="video/mp4"986                            )987                            988                            # Clean up temporary files989                            try:990                                os.remove(temp_path)991                                os.remove(output_path)992                                os.rmdir(temp_dir)993                                os.rmdir(output_dir)994                            except:995                                pass996            else:  # Usar c谩mara web997                st.subheader("Real-time facial feature detection")998                st.write("Click 'Start Camera' to begin real-time detection.")999                1000                # Placeholder for webcam video1001                camera_placeholder = st.empty()1002                1003                # Buttons to control the camera1004                col1, col2 = st.columns(2)1005                start_button = col1.button("Start Camera", on_click=start_feature_camera)1006                stop_button = col2.button("Stop Camera", on_click=stop_feature_camera)1007                1008                # Show message when camera is stopped1009                if 'feature_camera_stopped' in st.session_state and st.session_state.feature_camera_stopped:1010                    st.info("Camera stopped. Click 'Start Camera' to activate it again.")1011                    st.session_state.feature_camera_stopped = False1012                1013                if st.session_state.feature_camera_running:1014                    st.info("Camera activated. Processing real-time video with feature detection...")1015                    # Initialize webcam1016                    cap = cv2.VideoCapture(0)  # 0 is typically the main webcam1017                    1018                    if not cap.isOpened():1019                        st.error("Could not access webcam. Make sure it's connected and not being used by another application.")1020                        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.")1021                        st.session_state.feature_camera_running = False1022                    else:1023                        # Display real-time video with face and feature detection1024                        try:1025                            # Create placeholders for metrics1026                            metrics_placeholder = st.empty()1027                            metrics_col1, metrics_col2, metrics_col3 = metrics_placeholder.columns(3)1028                            1029                            # Initialize counters1030                            face_count_total = 01031                            eye_count_total = 01032                            smile_count_total = 01033                            frame_count = 01034                            1035                            while st.session_state.feature_camera_running:1036                                ret, frame = cap.read()1037                                if not ret:1038                                    st.error("Error reading frame from camera.")1039                                    break1040                                1041                                # Detect faces1042                                detections = detect_face_dnn(face_net, frame, conf_threshold)1043                                processed_frame, bboxes = process_face_detections(frame, detections, conf_threshold, bbox_color_bgr)1044                                1045                                # Update face counter1046                                face_count = len(bboxes)1047                                face_count_total += face_count1048                                1049                                # Initialize counters for this frame1050                                eye_count = 01051                                smile_count = 01052                                1053                                # Detect facial features if enabled1054                                if detect_eyes or detect_smile:1055                                    processed_frame, eye_count, smile_count = detect_facial_features(1056                                        processed_frame, 1057                                        bboxes,1058                                        eye_cascade,1059                                        smile_cascade,1060                                        detect_eyes,1061                                        detect_smile,1062                                        smile_sensitivity,1063                                        eye_sensitivity1064                                    )1065                                    1066                                    # Update total counters1067                                    eye_count_total += eye_count1068                                    smile_count_total += smile_count1069                                1070                                # Apply age/gender detection if enabled1071                                if detect_age_gender_option:1072                                    processed_frame = detect_age_gender(processed_frame, bboxes)1073                                1074                                # Display the processed frame1075                                camera_placeholder.image(processed_frame, channels="BGR", use_container_width=True)1076                                1077                                # Update frame counter1078                                frame_count += 11079                                1080                                # Update metrics every 5 frames to avoid overloading the interface1081                                if frame_count % 5 == 0:1082                                    metrics_col1.metric("Faces Detected", face_count)1083                                    1084                                    if detect_eyes:1085                                        metrics_col2.metric("Eyes Detected", eye_count)1086                                    else:1087                                        metrics_col2.metric("Eyes Detected", "N/A")1088                                    1089                                    if detect_smile:1090                                        metrics_col3.metric("Smiles Detected", smile_count)1091                                    else:1092                                        metrics_col3.metric("Smiles Detected", "N/A")1093                                1094                                # Small pause to avoid overloading the CPU1095                                time.sleep(0.01)1096                        finally:1097                            # Release the camera when stopped1098                            cap.release()1099 1100    elif app_mode == "Comparison Mode":1101        st.subheader("Face Comparison")1102        st.write("Upload two images to compare faces between them.")1103        1104        # A帽adir explicaci贸n sobre la interpretaci贸n de resultados1105        with st.expander("馃搶 How to interpret similarity results"):1106            st.markdown("""1107            ### Facial Similarity Interpretation Guide1108            1109            The system calculates similarity between faces based on multiple facial features and characteristics.1110            1111            **Similarity Ranges:**1112            - **70-100%**: HIGH Similarity - Very likely to be the same person or identical twins1113            - **50-70%**: MEDIUM Similarity - Possible match, requires verification1114            - **30-50%**: LOW Similarity - Different people with some similar features1115            - **0-30%**: VERY LOW Similarity - Completely different people1116            1117            **Enhanced Comparison System:**1118            The system uses a sophisticated approach that:1119            1. Analyzes multiple facial characteristics with advanced precision1120            2. Evaluates hair style/color, facial structure, texture patterns, and expressions with improved accuracy1121            3. Applies a balanced differentiation between similar and different individuals1122            4. Creates a clear gap between similar and different people's scores1123            5. Reduces scores for people with different facial structures1124            6. Applies penalty factors for critical differences in facial features1125            1126            **Features Analyzed:**1127            - Facial texture patterns (HOG features)1128            - Eye region characteristics (highly weighted)1129            - Nose bridge features1130            - Hair style and color patterns (enhanced detection)1131            - Precise facial proportions and structure1132            - Texture and edge patterns1133            - Facial expressions1134            - Critical difference markers (aspect ratio, brightness patterns, texture variance)1135            1136            **Factors affecting similarity:**1137            - Face angle and expression1138            - Lighting conditions1139            - Age differences1140            - Image quality1141            - Gender characteristics (with stronger weighting)1142            - Critical facial structure differences1143            1144            **Important note:** This system is designed to provide highly accurate similarity scores that create a clear distinction between different individuals while still recognizing truly similar people. The algorithm now applies multiple reduction factors to ensure that different people receive appropriately low similarity scores. For official identification, always use certified systems.1145            """)1146        1147        # Load face detection model1148        face_net = load_face_model()1149        1150        # Side-by-side file uploaders1151        col1, col2 = st.columns(2)1152        1153        with col1:1154            st.write("First Image")1155            file1 = st.file_uploader("Upload first image", type=['jpg', 'jpeg', 'png'], key="file1")1156        1157        with col2:1158            st.write("Second Image")1159            file2 = st.file_uploader("Upload second image", type=['jpg', 'jpeg', 'png'], key="file2")1160        1161        # Set confidence threshold1162        conf_threshold = st.slider("Face Detection Confidence", min_value=0.0, max_value=1.0, value=0.5, step=0.05)1163        1164        # Similarity threshold for considering a match1165        similarity_threshold = st.slider("Similarity Threshold (%)", min_value=35.0, max_value=95.0, value=45.0, step=5.0,1166                                        help="Minimum percentage of similarity to consider two faces as a match")1167        1168        # Selecci贸n del m茅todo de comparaci贸n1169        comparison_method = st.radio(1170            "Facial Comparison Method",1171            ["HOG (Fast, effective)", "Embeddings (Slow, more precise)"],1172            help="HOG uses histograms of oriented gradients for quick comparison. Embeddings use deep neural networks for greater precision."1173        )1174        1175        # Si se selecciona embeddings, mostrar opciones de modelos y advertencia1176        embedding_model = "VGG-Face"1177        if comparison_method == "Embeddings (Slow, more precise)" and DEEPFACE_AVAILABLE:1178            st.warning("WARNING: The current version of TensorFlow (2.19) may have incompatibilities with some models. It is recommended to use HOG if you experience problems.")1179            1180            embedding_model = st.selectbox(1181                "Embedding model",1182                ["VGG-Face", "Facenet", "OpenFace", "ArcFace"],  # Eliminado "DeepFace" de la lista1183                help="Select the neural network model to extract facial embeddings"1184            )1185        elif comparison_method == "Embeddings (Slow, more precise)" and not DEEPFACE_AVAILABLE:1186            st.warning("The DeepFace library is not available. Please install with 'pip install deepface' to use embeddings.")1187            st.info("Using HOG method by default.")1188            comparison_method = "HOG (Fast, effective)"1189        1190        # Style options1191        bbox_color = st.color_picker("Bounding Box Color", "#00FF00")1192        # Convert hex color to BGR for OpenCV1193        bbox_color_rgb = tuple(int(bbox_color.lstrip('#')[i:i+2], 16) for i in (0, 2, 4))1194        bbox_color_bgr = (bbox_color_rgb[2], bbox_color_rgb[1], bbox_color_rgb[0])  # Convert RGB to BGR1195        1196        # Process the images when both are uploaded1197        if file1 is not None and file2 is not None:1198            # Read both images1199            raw_bytes1 = np.asarray(bytearray(file1.read()), dtype=np.uint8)1200            image1 = cv2.imdecode(raw_bytes1, cv2.IMREAD_COLOR)

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