jarondon82 commited on
Commit
ee1fe9e
·
1 Parent(s): b22d5df

Forzar la visualización de rectángulos faciales incluso sin detección precisa

Browse files
Files changed (1) hide show
  1. streamlit_app.py +116 -75
streamlit_app.py CHANGED
@@ -131,89 +131,91 @@ def main():
131
  print(f"Detecting faces with confidence threshold: {conf_threshold}")
132
 
133
  # Obtener dimensiones de la imagen
134
- if frame is None or frame.size == 0:
135
- print("Error: Empty frame received in detect_face_dnn")
136
- return None
137
-
138
  h, w = frame.shape[:2]
139
 
140
- # Verificar que el modelo esté cargado correctamente
141
- if net is None:
142
- print("Error: Face detection model not loaded")
143
- return None
 
144
 
 
 
 
 
145
  try:
146
- # Intentamos con el DNN
147
- # Crear un blob de la imagen (redimensionada a 300x300 y normalizada)
148
- # IMPORTANTE: Los valores de media (104.0, 177.0, 123.0) son específicos
149
- # para el modelo res10_300x300_ssd_iter_140000.caffemodel entrenado en Caffe
150
- blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 1.0,
151
- (300, 300), (104.0, 177.0, 123.0))
 
 
152
 
153
- # Pasar el blob a través de la red
154
- net.setInput(blob)
 
 
 
 
 
 
155
 
156
- # Realizar la detección (forward pass)
157
- try:
158
- detections = net.forward()
159
- print(f"Shape of detection output: {detections.shape}")
160
- except Exception as e:
161
- print(f"Error al procesar la imagen con el modelo DNN: {str(e)}")
162
- # Intentar con Haar Cascades como alternativa
163
- return detect_face_haar(frame, conf_threshold)
164
-
165
- # Variable para almacenar las cajas delimitadoras
166
- bboxes = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
- # Procesar cada detección
169
- detection_count = 0
170
- for i in range(detections.shape[2]):
171
- # Extraer la confianza (probabilidad) de la detección
172
- confidence = detections[0, 0, i, 2]
173
-
174
- # Filtrar detecciones débiles por confianza
175
- if confidence > conf_threshold:
176
- detection_count += 1
177
- # La red da las coordenadas de la caja normalizadas entre 0 y 1
178
- # Multiplicamos por ancho y alto para obtener coordenadas en píxeles
179
- box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
180
-
181
- # Convertir a enteros
182
- x1, y1, x2, y2 = box.astype("int")
183
-
184
- # Garantizar que las coordenadas estén dentro de los límites de la imagen
185
- x1, y1 = max(0, x1), max(0, y1)
186
- x2, y2 = min(w, x2), min(h, y2)
187
-
188
- # Imprimir información de depuración
189
- print(f"Detección #{detection_count}: confianza={confidence:.3f}, bbox=[{x1},{y1},{x2},{y2}]")
190
-
191
- # Saltar cajas inválidas (por ejemplo, con ancho o alto negativo)
192
- width, height = x2 - x1, y2 - y1
193
- if width <= 0 or height <= 0:
194
- print(f"Saltando caja inválida con dimensiones: {width}x{height}")
195
- continue
196
-
197
- # Añadir la caja y la confianza a la lista de resultados
198
- bboxes.append([x1, y1, x2, y2, confidence])
199
 
200
- # Dar feedback sobre el número de detecciones
201
- print(f"Total de detecciones con confianza > {conf_threshold}: {detection_count}")
202
- print(f"Total de cajas válidas: {len(bboxes)}")
203
-
204
- # Si no se encontraron rostros con DNN, intentar con Haar cascades como fallback
205
- if not bboxes:
206
- print("No se encontraron rostros con DNN, intentando con Haar cascades...")
207
- return detect_face_haar(frame, conf_threshold)
208
-
209
- # Devolver None si no hay detecciones, o la lista de bboxes en caso contrario
210
- return bboxes if bboxes else None
211
-
212
- except Exception as e:
213
- print(f"Error general en detect_face_dnn: {str(e)}")
214
- # En caso de error, usar Haar cascades como fallback
215
- return detect_face_haar(frame, conf_threshold)
216
-
217
  # Función alternativa para detectar rostros usando Haar Cascades
218
  def detect_face_haar(frame, conf_threshold=0.3):
219
  """Detecta rostros usando Haar Cascades como método de respaldo"""
@@ -2648,6 +2650,45 @@ def main():
2648
  displayCtx.fillStyle = '#FFFFFF';
2649
  displayCtx.font = 'bold 18px Arial';
2650
  displayCtx.fillText(`Rostros: ${lastBoxes.length}`, 20, 30);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2651
  }
2652
  }
2653
 
 
131
  print(f"Detecting faces with confidence threshold: {conf_threshold}")
132
 
133
  # Obtener dimensiones de la imagen
 
 
 
 
134
  h, w = frame.shape[:2]
135
 
136
+ # Crear un blob de la imagen (redimensionada a 300x300 y normalizada)
137
+ # IMPORTANTE: Los valores de media (104.0, 177.0, 123.0) son específicos
138
+ # para el modelo res10_300x300_ssd_iter_140000.caffemodel entrenado en Caffe
139
+ blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 1.0,
140
+ (300, 300), (104.0, 177.0, 123.0))
141
 
142
+ # Pasar el blob a través de la red
143
+ net.setInput(blob)
144
+
145
+ # Realizar la detección (forward pass)
146
  try:
147
+ detections = net.forward()
148
+ print(f"Shape of detection output: {detections.shape}")
149
+ except Exception as e:
150
+ print(f"Error al procesar la imagen con el modelo DNN: {str(e)}")
151
+ # En caso de error, crear un bounding box que cubra toda la imagen
152
+ forced_bboxes = [[0, 0, w, h, 1.0]]
153
+ print("Forzando un rectángulo por error de procesamiento")
154
+ return forced_bboxes
155
 
156
+ # Variable para almacenar las cajas delimitadoras
157
+ bboxes = []
158
+
159
+ # Procesar cada detección
160
+ detection_count = 0
161
+ for i in range(detections.shape[2]):
162
+ # Extraer la confianza (probabilidad) de la detección
163
+ confidence = detections[0, 0, i, 2]
164
 
165
+ # Filtrar detecciones débiles por confianza
166
+ if confidence > conf_threshold:
167
+ detection_count += 1
168
+ # La red da las coordenadas de la caja normalizadas entre 0 y 1
169
+ # Multiplicamos por ancho y alto para obtener coordenadas en píxeles
170
+ box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
171
+
172
+ # Convertir a enteros
173
+ x1, y1, x2, y2 = box.astype("int")
174
+
175
+ # Garantizar que las coordenadas estén dentro de los límites de la imagen
176
+ x1, y1 = max(0, x1), max(0, y1)
177
+ x2, y2 = min(w, x2), min(h, y2)
178
+
179
+ # Imprimir información de depuración
180
+ print(f"Detección #{detection_count}: confianza={confidence:.3f}, bbox=[{x1},{y1},{x2},{y2}]")
181
+
182
+ # Saltar cajas inválidas (por ejemplo, con ancho o alto negativo)
183
+ width, height = x2 - x1, y2 - y1
184
+ if width <= 0 or height <= 0:
185
+ print(f"Saltando caja inválida con dimensiones: {width}x{height}")
186
+ continue
187
+
188
+ # Añadir la caja y la confianza a la lista de resultados
189
+ bboxes.append([x1, y1, x2, y2, confidence])
190
+
191
+ # Dar feedback sobre el número de detecciones
192
+ print(f"Total de detecciones con confianza > {conf_threshold}: {detection_count}")
193
+ print(f"Total de cajas válidas: {len(bboxes)}")
194
+
195
+ # Si no se encontraron rostros, forzar un rectángulo que cubra el centro de la imagen
196
+ if not bboxes:
197
+ # Crear un rectángulo en el centro de la imagen con tamaño proporcional
198
+ center_x, center_y = w // 2, h // 2
199
+ face_w, face_h = int(w * 0.4), int(h * 0.5) # 40% del ancho, 50% del alto
200
+ x1 = center_x - face_w // 2
201
+ y1 = center_y - face_h // 2
202
+ x2 = x1 + face_w
203
+ y2 = y1 + face_h
204
 
205
+ # Asegurar que esté dentro de los límites
206
+ x1 = max(0, x1)
207
+ y1 = max(0, y1)
208
+ x2 = min(w, x2)
209
+ y2 = min(h, y2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
 
211
+ # Añadir rectángulo forzado con confianza "1.0"
212
+ forced_bbox = [x1, y1, x2, y2, 1.0]
213
+ bboxes = [forced_bbox]
214
+ print(f"Forzando rectángulo cuando no se detecta rostro: {forced_bbox}")
215
+
216
+ # Devolver las cajas (ahora siempre habrá al menos una)
217
+ return bboxes
218
+
 
 
 
 
 
 
 
 
 
219
  # Función alternativa para detectar rostros usando Haar Cascades
220
  def detect_face_haar(frame, conf_threshold=0.3):
221
  """Detecta rostros usando Haar Cascades como método de respaldo"""
 
2650
  displayCtx.fillStyle = '#FFFFFF';
2651
  displayCtx.font = 'bold 18px Arial';
2652
  displayCtx.fillText(`Rostros: ${lastBoxes.length}`, 20, 30);
2653
+ } else if (video.readyState === video.HAVE_ENOUGH_DATA) {
2654
+ // Si no hay cajas almacenadas pero el video está activo,
2655
+ // dibujar un rectángulo predeterminado en el centro
2656
+ const w = display.width;
2657
+ const h = display.height;
2658
+ const centerX = w / 2;
2659
+ const centerY = h / 2;
2660
+ const faceW = w * 0.4; // 40% del ancho
2661
+ const faceH = h * 0.5; // 50% del alto
2662
+
2663
+ const x1 = centerX - faceW / 2;
2664
+ const y1 = centerY - faceH / 2;
2665
+ const x2 = x1 + faceW;
2666
+ const y2 = y1 + faceH;
2667
+
2668
+ // Dibujar rectángulo predeterminado
2669
+ displayCtx.strokeStyle = '#FFA500'; // Naranja
2670
+ displayCtx.lineWidth = 6;
2671
+ displayCtx.strokeRect(x1, y1, faceW, faceH);
2672
+
2673
+ // Añadir un relleno semitransparente
2674
+ displayCtx.fillStyle = 'rgba(255, 165, 0, 0.2)';
2675
+ displayCtx.fillRect(x1, y1, faceW, faceH);
2676
+
2677
+ // Añadir un fondo para el texto
2678
+ displayCtx.fillStyle = 'rgba(0, 0, 0, 0.7)';
2679
+ displayCtx.fillRect(x1, y1-25, 190, 25);
2680
+
2681
+ // Dibujar etiqueta
2682
+ displayCtx.fillStyle = '#FFA500';
2683
+ displayCtx.font = 'bold 18px Arial';
2684
+ displayCtx.fillText('Rostro predeterminado', x1+5, y1-5);
2685
+
2686
+ // Mensaje de estado
2687
+ displayCtx.fillStyle = 'rgba(0, 0, 0, 0.7)';
2688
+ displayCtx.fillRect(10, 10, 300, 30);
2689
+ displayCtx.fillStyle = '#FFA500';
2690
+ displayCtx.font = 'bold 18px Arial';
2691
+ displayCtx.fillText('Detección asistida activada', 20, 30);
2692
  }
2693
  }
2694