# Simple app.py for Face Detection import os import streamlit as st import cv2 import numpy as np from PIL import Image import io import base64 import logging # Configurar logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # Comprobar y descargar modelos necesarios try: # Verificar si los archivos de modelo existen model_files = [ "deploy.prototxt.txt", "res10_300x300_ssd_iter_140000.caffemodel" ] missing_files = [f for f in model_files if not os.path.exists(f)] if missing_files: st.warning("Faltan archivos de modelo. Descargando...") import download_models download_models.main() st.success("¡Archivos de modelo descargados correctamente!") except Exception as e: st.error(f"Error al comprobar/descargar modelos: {e}") # Modo diagnóstico if 'modo_diagnostico' not in st.session_state: st.session_state.modo_diagnostico = False # Función para el modo de diagnóstico def modo_diagnostico(): st.title("Diagnóstico de Detección Facial") st.write("Esta herramienta ayuda a identificar problemas con la detección de rostros.") # Verificar modelos st.subheader("1. Verificación de archivos de modelo") for archivo in model_files: if os.path.exists(archivo): st.success(f"✅ Modelo encontrado: {archivo}") st.write(f"Tamaño: {os.path.getsize(archivo)} bytes") else: st.error(f"❌ Modelo NO encontrado: {archivo}") # Probar carga del modelo st.subheader("2. Prueba de carga del modelo") try: modelFile = "res10_300x300_ssd_iter_140000.caffemodel" configFile = "deploy.prototxt.txt" # Cargar modelos st.write("Intentando cargar el modelo DNN...") try: net = cv2.dnn.readNetFromCaffe(configFile, modelFile) st.success(f"✅ Modelo DNN cargado correctamente: {type(net)}") st.write(f"Información del modelo: {str(net)}") except Exception as e: st.error(f"❌ Error al cargar el modelo DNN: {e}") st.warning("Intentando cargar cascadas Haar como alternativa...") # Cargar cascadas Haar como alternativa st.write("Cargando modelos de cascada Haar...") try: # Obtener la ruta a los archivos de cascada haar_face_path = cv2.data.haarcascades + 'haarcascade_frontalface_default.xml' st.write(f"Ruta a Haar Cascade: {haar_face_path}") haar_face = cv2.CascadeClassifier(haar_face_path) if haar_face.empty(): st.error("❌ El clasificador de Haar no se cargó correctamente") else: st.success("✅ Cascada Haar para rostros cargada correctamente") except Exception as e: st.error(f"❌ Error al cargar cascadas Haar: {e}") # Crear imagen de prueba st.subheader("3. Probar detección con imagen sintética") # Crear una imagen de prueba con un óvalo como rostro example_image = np.zeros((400, 400, 3), dtype=np.uint8) # Dibujar un óvalo que simule un rostro cv2.ellipse(example_image, (200, 200), (100, 140), 0, 0, 360, (200, 200, 200), -1) # Dibujar ojos cv2.circle(example_image, (150, 150), 15, (255, 255, 255), -1) cv2.circle(example_image, (250, 150), 15, (255, 255, 255), -1) # Dibujar boca cv2.ellipse(example_image, (200, 250), (50, 20), 0, 0, 360, (150, 150, 150), -1) # Mostrar imagen de prueba st.image(example_image, caption="Imagen de prueba", channels="BGR") # Detectar rostros con DNN st.subheader("4. Prueba de detección con DNN") umbral = st.slider("Umbral de confianza DNN", 0.1, 0.9, 0.3, 0.1) try: # Detectar rostros en la imagen de prueba con DNN h, w = example_image.shape[:2] blob = cv2.dnn.blobFromImage(cv2.resize(example_image, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0)) net.setInput(blob) detections = net.forward() # Procesar detecciones bboxes = [] frame_h, frame_w = example_image.shape[:2] for i in range(detections.shape[2]): confidence = detections[0, 0, i, 2] if confidence > umbral: box = detections[0, 0, i, 3:7] * np.array([frame_w, frame_h, frame_w, frame_h]) x1, y1, x2, y2 = box.astype("int") # Asegurar coordenadas válidas x1 = max(0, min(x1, frame_w - 1)) y1 = max(0, min(y1, frame_h - 1)) x2 = max(0, min(x2, frame_w - 1)) y2 = max(0, min(y2, frame_h - 1)) # Verificar validez de la caja width, height = x2 - x1, y2 - y1 if width <= 0 or height <= 0: continue bboxes.append([x1, y1, x2, y2, confidence]) # Dibujar resultados result_image = example_image.copy() for bbox in bboxes: x1, y1, x2, y2, confidence = bbox # Dibujar rectángulo verde grueso cv2.rectangle(result_image, (x1, y1), (x2, y2), (0, 255, 0), 3) # Añadir texto con confianza cv2.putText(result_image, f"{confidence:.2f}", (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) st.image(result_image, caption=f"Resultado con DNN (umbral {umbral})", channels="BGR") # Mostrar estadísticas st.write(f"Detecciones encontradas con DNN: {len(bboxes)}") if len(bboxes) > 0: st.success("✅ La detección DNN funciona correctamente") else: st.error("❌ No se detectaron rostros con DNN") # Mostrar valores de confianza st.write("Valores de confianza detectados:") confianzas = [] for i in range(min(10, detections.shape[2])): confianza = detections[0, 0, i, 2] confianzas.append(confianza) st.write(confianzas) except Exception as e: st.error(f"Error en detección DNN: {e}") # Prueba con Haar Cascade st.subheader("5. Prueba de detección con Haar (alternativa)") try: # Convertir a escala de grises gray = cv2.cvtColor(example_image, cv2.COLOR_BGR2GRAY) # Detectar rostros faces = haar_face.detectMultiScale( gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags=cv2.CASCADE_SCALE_IMAGE ) # Dibujar resultados haar_result = example_image.copy() for (x, y, w, h) in faces: cv2.rectangle(haar_result, (x, y), (x+w, y+h), (0, 255, 0), 3) st.image(haar_result, caption="Resultado con Haar Cascade", channels="BGR") st.write(f"Rostros detectados con Haar: {len(faces)}") if len(faces) > 0: st.success("✅ La detección con Haar funciona correctamente") else: st.error("❌ No se detectaron rostros con Haar") except Exception as e: st.error(f"Error en detección Haar: {e}") # Probar con imagen real st.subheader("6. Prueba con imagen de rostro real") # Crear una imagen realista de prueba real_face = np.ones((400, 400, 3), dtype=np.uint8) * 200 # Fondo gris claro # Dibujar un rostro más realista (óvalo de color piel) cv2.ellipse(real_face, (200, 200), (120, 170), 0, 0, 360, (50, 140, 220), -1) # BGR # Dibujar ojos (elipses con iris y pupilas) # Ojo izquierdo cv2.ellipse(real_face, (150, 150), (25, 15), 0, 0, 360, (255, 255, 255), -1) # Blanco del ojo cv2.circle(real_face, (150, 150), 10, (80, 120, 180), -1) # Iris cv2.circle(real_face, (150, 150), 5, (20, 20, 20), -1) # Pupila # Ojo derecho cv2.ellipse(real_face, (250, 150), (25, 15), 0, 0, 360, (255, 255, 255), -1) # Blanco del ojo cv2.circle(real_face, (250, 150), 10, (80, 120, 180), -1) # Iris cv2.circle(real_face, (250, 150), 5, (20, 20, 20), -1) # Pupila # Dibujar nariz nose_points = np.array([[200, 180], [180, 220], [220, 220]], np.int32) nose_points = nose_points.reshape((-1, 1, 2)) cv2.fillPoly(real_face, [nose_points], (40, 120, 200)) # Dibujar boca (sonrisa) cv2.ellipse(real_face, (200, 260), (60, 25), 0, 0, 180, (40, 80, 200), -1) # Mostrar imagen st.image(real_face, caption="Imagen realista de prueba", channels="BGR") # Detectar rostros con DNN en la imagen realista try: h, w = real_face.shape[:2] blob = cv2.dnn.blobFromImage(cv2.resize(real_face, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0)) net.setInput(blob) detections = net.forward() bboxes = [] for i in range(detections.shape[2]): confidence = detections[0, 0, i, 2] if confidence > umbral: box = detections[0, 0, i, 3:7] * np.array([w, h, w, h]) x1, y1, x2, y2 = box.astype("int") # Asegurar coordenadas válidas x1 = max(0, min(x1, w - 1)) y1 = max(0, min(y1, h - 1)) x2 = max(0, min(x2, w - 1)) y2 = max(0, min(y2, h - 1)) # Verificar validez de la caja width, height = x2 - x1, y2 - y1 if width <= 0 or height <= 0: continue bboxes.append([x1, y1, x2, y2, confidence]) # Dibujar resultados real_result = real_face.copy() for bbox in bboxes: x1, y1, x2, y2, confidence = bbox # Dibujar rectángulo verde grueso cv2.rectangle(real_result, (x1, y1), (x2, y2), (0, 255, 0), 3) # Añadir texto con confianza cv2.putText(real_result, f"{confidence:.2f}", (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) st.image(real_result, caption=f"Imagen realista con DNN (umbral {umbral})", channels="BGR") st.write(f"Detecciones en imagen realista: {len(bboxes)}") if len(bboxes) > 0: st.success("✅ La detección en imagen realista funciona correctamente") else: st.error("❌ No se detectaron rostros en la imagen realista") except Exception as e: st.error(f"Error en detección de imagen realista: {e}") # Diagnóstico final st.subheader("Diagnóstico y recomendaciones") if len(bboxes) == 0: st.write(""" ### Posibles problemas: 1. **El modelo no se está cargando correctamente.** - Verifique que los archivos existan y tengan el tamaño correcto. - Intente descargar los modelos manualmente en la misma carpeta. 2. **El procesamiento de la imagen es incorrecto.** - La transformación blob podría estar mal configurada. - Intente usar diferentes preprocesamiento de la imagen. 3. **El umbral de confianza es demasiado alto.** - Pruebe umbrales más bajos como 0.1 o 0.2. - Ajuste la sensibilidad de detección. 4. **Hay un problema con la visualización de los resultados.** - Verifique el código que dibuja los rectángulos. - Asegúrese de que las coordenadas sean válidas. ### Soluciones para la aplicación principal: 1. Intente usar Haar Cascades en lugar del modelo DNN. 2. Ajuste el umbral de confianza a un valor más bajo. 3. Verifique la conversión de color BGR a RGB en la visualización. 4. Intente usar otro modelo de detección facial como MediaPipe. """) else: st.write(""" ### La detección facial funciona en el diagnóstico, pero no en la aplicación principal Esto sugiere que hay algún problema en la aplicación principal, no en el modelo. Revise: 1. Cómo se procesan las imágenes en la aplicación principal 2. El código que dibuja los rectángulos verdes 3. La conversión de color BGR a RGB para visualización 4. Los umbrales de confianza utilizados """) except Exception as e: st.error(f"Error general en el diagnóstico: {e}") # Crear un sidebar con opciones st.sidebar.title("Opciones") modo = st.sidebar.radio("Seleccionar modo:", ["Aplicación principal", "Diagnóstico"]) if modo == "Diagnóstico": # Ejecutar diagnóstico modo_diagnostico() else: # Ejecutar aplicación principal try: # Importar la aplicación principal print("Starting Face Detection Application...") from streamlit_app import main # Main entry point if __name__ == "__main__": main() except Exception as e: st.error(f"Error al iniciar la aplicación: {e}") st.error("Por favor, revise los logs para más información.")