Spaces:
Build error
Build error
| # 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.") |