jarondon82 commited on
Commit
2c2574b
·
1 Parent(s): ca08464

Mejora deteccion facial

Browse files
Files changed (1) hide show
  1. streamlit_app.py +96 -48
streamlit_app.py CHANGED
@@ -117,6 +117,7 @@ def main():
117
  def detect_face_dnn(net, frame, conf_threshold=0.3):
118
  """
119
  Detecta rostros en una imagen utilizando un modelo DNN pre-entrenado.
 
120
 
121
  Args:
122
  net: Modelo DNN cargado
@@ -134,7 +135,7 @@ def main():
134
  log_info += f"Forma de la imagen: {frame.shape}\n"
135
 
136
  # Forzar un umbral muy bajo para aumentar la sensibilidad
137
- internal_threshold = 0.1 # Usar este umbral internamente para mayor sensibilidad
138
 
139
  # Añadir impresión de depuración para el umbral usado
140
  print(f"Detecting faces with original threshold: {conf_threshold}, using internal threshold: {internal_threshold}")
@@ -156,7 +157,7 @@ def main():
156
  with open("diagnostico_deteccion.txt", "a") as f:
157
  f.write(log_info)
158
  print(log_info)
159
- return []
160
 
161
  # Pasar el blob a través de la red
162
  try:
@@ -167,7 +168,7 @@ def main():
167
  with open("diagnostico_deteccion.txt", "a") as f:
168
  f.write(log_info)
169
  print(log_info)
170
- return []
171
 
172
  # Realizar la detección (forward pass)
173
  try:
@@ -241,7 +242,7 @@ def main():
241
  # Verificar si hay detecciones con umbral más bajo para depuración
242
  for i in range(detections.shape[2]):
243
  confidence = detections[0, 0, i, 2]
244
- if confidence > 0.05: # Umbral muy bajo para depuración
245
  box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
246
  x1, y1, x2, y2 = box.astype("int")
247
  log_info += f"Detección de baja confianza: {confidence:.3f} en [{x1},{y1},{x2},{y2}]\n"
@@ -295,38 +296,48 @@ def main():
295
  # Ecualizar el histograma para mejorar contraste
296
  gray = cv2.equalizeHist(gray)
297
 
298
- # Detectar rostros - la confianza se controla con minNeighbors
299
- # Usamos el umbral de confianza como guía para minNeighbors
300
- min_neighbors = max(3, int(conf_threshold * 10))
 
 
 
301
  faces = st.session_state.haar_face_cascade.detectMultiScale(
302
  gray,
303
- scaleFactor=1.1,
304
  minNeighbors=min_neighbors,
305
- minSize=(30, 30),
306
  flags=cv2.CASCADE_SCALE_IMAGE
307
  )
308
 
309
- print(f"Haar cascade found {len(faces)} faces")
310
-
311
- # Convertir al formato [x1, y1, x2, y2, confidence]
312
- # Note que Haar Cascades no proporciona un valor de confianza real
313
  bboxes = []
314
  for (x, y, w, h) in faces:
315
- # Usamos un valor fijo de confianza de 0.8 para Haar detections
316
- # Esto es arbitrario pero útil para el procesamiento posterior
317
- bboxes.append([x, y, x+w, y+h, 0.8])
318
 
319
- return bboxes if bboxes else None
320
 
321
  except Exception as e:
322
- print(f"Error en detect_face_haar: {str(e)}")
323
- return None
324
 
325
  # Function for processing face detections
326
  def process_face_detections(frame, detections, conf_threshold=0.5, bbox_color=(0, 255, 0)):
327
  # Create a copy for drawing on
328
  result_frame = frame.copy()
329
 
 
 
 
 
 
 
 
 
 
 
330
  # Procesar detecciones si son del formato original
331
  if isinstance(detections, np.ndarray) and len(detections.shape) == 4:
332
  bboxes = []
@@ -335,7 +346,12 @@ def main():
335
 
336
  for i in range(detections.shape[2]):
337
  confidence = detections[0, 0, i, 2]
338
- if confidence > conf_threshold:
 
 
 
 
 
339
  x1 = int(detections[0, 0, i, 3] * frame_w)
340
  y1 = int(detections[0, 0, i, 4] * frame_h)
341
  x2 = int(detections[0, 0, i, 5] * frame_w)
@@ -347,29 +363,40 @@ def main():
347
  x2 = max(0, min(x2, frame_w - 1))
348
  y2 = max(0, min(y2, frame_h - 1))
349
 
350
- # Dibujar el bounding box
351
- cv2.rectangle(result_frame, (x1, y1), (x2, y2), bbox_color, 2)
 
 
 
 
352
 
353
  # Añadir texto con la confianza
354
  label = f"{confidence:.2f}"
355
- cv2.putText(result_frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, bbox_color, 2)
356
 
357
  # Añadir a la lista de bounding boxes
358
  bboxes.append([x1, y1, x2, y2, confidence])
359
  else:
360
  # Si ya es una lista de bounding boxes (formato nuevo)
361
- bboxes = detections
 
362
  # Dibujar bounding boxes
363
  for bbox in bboxes:
364
  if len(bbox) == 5: # Asegurarse de que el bounding box tiene el formato correcto
365
  x1, y1, x2, y2, confidence = bbox
366
- if confidence >= conf_threshold:
367
- # Dibujar el bounding box
368
- cv2.rectangle(result_frame, (x1, y1), (x2, y2), bbox_color, 2)
369
-
370
- # Añadir texto con la confianza
371
- label = f"{confidence:.2f}"
372
- cv2.putText(result_frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, bbox_color, 2)
 
 
 
 
 
 
373
 
374
  return result_frame, bboxes
375
 
@@ -840,6 +867,19 @@ def main():
840
  # File uploader for images
841
  file_buffer = st.file_uploader("Upload an image", type=['jpg', 'jpeg', 'png'])
842
 
 
 
 
 
 
 
 
 
 
 
 
 
 
843
  if file_buffer is not None:
844
  # Read the file and convert it to OpenCV format
845
  raw_bytes = np.asarray(bytearray(file_buffer.read()), dtype=np.uint8)
@@ -874,29 +914,18 @@ def main():
874
  st.subheader("Processed Image")
875
  st.image(processed_image, channels='BGR', use_container_width=True)
876
 
 
 
 
 
 
 
877
  # Convert OpenCV image to PIL for download
878
  pil_img = Image.fromarray(processed_image[:, :, ::-1])
879
  st.markdown(
880
  get_image_download_link(pil_img, "face_detection_result.jpg", "📥 Download Processed Image"),
881
  unsafe_allow_html=True
882
  )
883
-
884
- # Show metrics if enabled
885
- if show_metrics:
886
- st.subheader("Processing Metrics")
887
- col1, col2, col3 = st.columns(3)
888
- col1.metric("Processing Time", f"{processing_time:.4f} seconds")
889
- col2.metric("Faces Detected", len(bboxes))
890
- col3.metric("Confidence Threshold", f"{conf_threshold:.2f}")
891
-
892
- # Display detailed metrics in an expandable section
893
- with st.expander("Detailed Detection Information"):
894
- if bboxes:
895
- st.write("Detected faces with confidence scores:")
896
- for i, bbox in enumerate(bboxes):
897
- st.write(f"Face #{i+1}: Confidence = {bbox[4]:.4f}")
898
- else:
899
- st.write("No faces detected in the image.")
900
 
901
  else: # Video mode
902
  # Video mode options
@@ -1082,6 +1111,19 @@ def main():
1082
  # File uploader for images
1083
  file_buffer = st.file_uploader("Upload an image", type=['jpg', 'jpeg', 'png'])
1084
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1085
  if file_buffer is not None:
1086
  # Read the file and convert it to OpenCV format
1087
  raw_bytes = np.asarray(bytearray(file_buffer.read()), dtype=np.uint8)
@@ -1131,6 +1173,12 @@ def main():
1131
  st.subheader("Processed Image")
1132
  st.image(processed_image, channels='BGR', use_container_width=True)
1133
 
 
 
 
 
 
 
1134
  # Convert OpenCV image to PIL for download
1135
  pil_img = Image.fromarray(processed_image[:, :, ::-1])
1136
  st.markdown(
 
117
  def detect_face_dnn(net, frame, conf_threshold=0.3):
118
  """
119
  Detecta rostros en una imagen utilizando un modelo DNN pre-entrenado.
120
+ Si no se detectan rostros, usa automáticamente Haar Cascades como respaldo.
121
 
122
  Args:
123
  net: Modelo DNN cargado
 
135
  log_info += f"Forma de la imagen: {frame.shape}\n"
136
 
137
  # Forzar un umbral muy bajo para aumentar la sensibilidad
138
+ internal_threshold = 0.05 # Usar este umbral internamente para mayor sensibilidad
139
 
140
  # Añadir impresión de depuración para el umbral usado
141
  print(f"Detecting faces with original threshold: {conf_threshold}, using internal threshold: {internal_threshold}")
 
157
  with open("diagnostico_deteccion.txt", "a") as f:
158
  f.write(log_info)
159
  print(log_info)
160
+ return detect_face_haar(frame, conf_threshold)
161
 
162
  # Pasar el blob a través de la red
163
  try:
 
168
  with open("diagnostico_deteccion.txt", "a") as f:
169
  f.write(log_info)
170
  print(log_info)
171
+ return detect_face_haar(frame, conf_threshold)
172
 
173
  # Realizar la detección (forward pass)
174
  try:
 
242
  # Verificar si hay detecciones con umbral más bajo para depuración
243
  for i in range(detections.shape[2]):
244
  confidence = detections[0, 0, i, 2]
245
+ if confidence > 0.01: # Umbral extremadamente bajo para depuración
246
  box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
247
  x1, y1, x2, y2 = box.astype("int")
248
  log_info += f"Detección de baja confianza: {confidence:.3f} en [{x1},{y1},{x2},{y2}]\n"
 
296
  # Ecualizar el histograma para mejorar contraste
297
  gray = cv2.equalizeHist(gray)
298
 
299
+ # Parámetros más sensibles para la detección con Haar
300
+ scale_factor = 1.05 # Más lento pero más preciso (era 1.1)
301
+ min_neighbors = 3 # Valor más bajo, más detecciones pero más falsos positivos (era 5)
302
+ min_size = (20, 20) # Tamaño mínimo más pequeño (era 30, 30)
303
+
304
+ # Detectar rostros con clasificador Haar
305
  faces = st.session_state.haar_face_cascade.detectMultiScale(
306
  gray,
307
+ scaleFactor=scale_factor,
308
  minNeighbors=min_neighbors,
309
+ minSize=min_size,
310
  flags=cv2.CASCADE_SCALE_IMAGE
311
  )
312
 
313
+ # Convertir a formato bounding box [x1, y1, x2, y2, confianza]
 
 
 
314
  bboxes = []
315
  for (x, y, w, h) in faces:
316
+ # Usar un valor de confianza fijo para las detecciones Haar
317
+ confidence = 0.8 # Valor arbitrario alto
318
+ bboxes.append([x, y, x + w, y + h, confidence])
319
 
320
+ return bboxes
321
 
322
  except Exception as e:
323
+ print(f"Error en detección Haar: {e}")
324
+ return []
325
 
326
  # Function for processing face detections
327
  def process_face_detections(frame, detections, conf_threshold=0.5, bbox_color=(0, 255, 0)):
328
  # Create a copy for drawing on
329
  result_frame = frame.copy()
330
 
331
+ # Asegurar que bbox_color sea una tupla de 3 elementos para BGR
332
+ if isinstance(bbox_color, tuple) and len(bbox_color) == 3:
333
+ bbox_color_bgr = bbox_color
334
+ else:
335
+ # Usar verde como color predeterminado
336
+ bbox_color_bgr = (0, 255, 0)
337
+
338
+ # Definir grosor para los rectángulos (más grueso para mejor visibilidad)
339
+ thickness = 3
340
+
341
  # Procesar detecciones si son del formato original
342
  if isinstance(detections, np.ndarray) and len(detections.shape) == 4:
343
  bboxes = []
 
346
 
347
  for i in range(detections.shape[2]):
348
  confidence = detections[0, 0, i, 2]
349
+ print(f"Confidence: {confidence}, Threshold: {conf_threshold}")
350
+
351
+ # Usar un umbral muy bajo para mejorar la detección
352
+ effective_threshold = max(0.05, conf_threshold)
353
+
354
+ if confidence > effective_threshold:
355
  x1 = int(detections[0, 0, i, 3] * frame_w)
356
  y1 = int(detections[0, 0, i, 4] * frame_h)
357
  x2 = int(detections[0, 0, i, 5] * frame_w)
 
363
  x2 = max(0, min(x2, frame_w - 1))
364
  y2 = max(0, min(y2, frame_h - 1))
365
 
366
+ # Verificar que el rectángulo es válido
367
+ if x2 <= x1 or y2 <= y1:
368
+ continue
369
+
370
+ # Dibujar el bounding box con línea más gruesa
371
+ cv2.rectangle(result_frame, (x1, y1), (x2, y2), bbox_color_bgr, thickness)
372
 
373
  # Añadir texto con la confianza
374
  label = f"{confidence:.2f}"
375
+ cv2.putText(result_frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, bbox_color_bgr, 2)
376
 
377
  # Añadir a la lista de bounding boxes
378
  bboxes.append([x1, y1, x2, y2, confidence])
379
  else:
380
  # Si ya es una lista de bounding boxes (formato nuevo)
381
+ bboxes = detections if detections is not None else []
382
+
383
  # Dibujar bounding boxes
384
  for bbox in bboxes:
385
  if len(bbox) == 5: # Asegurarse de que el bounding box tiene el formato correcto
386
  x1, y1, x2, y2, confidence = bbox
387
+
388
+ # Usar un umbral bajo para la visualización
389
+ effective_threshold = max(0.05, conf_threshold)
390
+
391
+ if confidence >= effective_threshold:
392
+ # Verificar que las coordenadas son válidas
393
+ if x1 >= 0 and y1 >= 0 and x2 > x1 and y2 > y1:
394
+ # Dibujar el bounding box con línea más gruesa
395
+ cv2.rectangle(result_frame, (x1, y1), (x2, y2), bbox_color_bgr, thickness)
396
+
397
+ # Añadir texto con la confianza
398
+ label = f"{confidence:.2f}"
399
+ cv2.putText(result_frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, bbox_color_bgr, 2)
400
 
401
  return result_frame, bboxes
402
 
 
867
  # File uploader for images
868
  file_buffer = st.file_uploader("Upload an image", type=['jpg', 'jpeg', 'png'])
869
 
870
+ # Umbral de confianza ajustable
871
+ conf_threshold = st.slider(
872
+ "Umbral de confianza",
873
+ min_value=0.05,
874
+ max_value=0.95,
875
+ value=0.2, # Valor por defecto más bajo (era 0.5)
876
+ step=0.05,
877
+ help="Ajusta este valor para controlar la sensibilidad de la detección facial. Un valor más bajo detecta más rostros pero puede tener falsos positivos."
878
+ )
879
+
880
+ # Color del bounding box
881
+ bbox_color_bgr = (0, 255, 0) # Verde brillante para mejor visibilidad
882
+
883
  if file_buffer is not None:
884
  # Read the file and convert it to OpenCV format
885
  raw_bytes = np.asarray(bytearray(file_buffer.read()), dtype=np.uint8)
 
914
  st.subheader("Processed Image")
915
  st.image(processed_image, channels='BGR', use_container_width=True)
916
 
917
+ # Mostrar mensaje sobre lo que se está viendo
918
+ if len(bboxes) > 0:
919
+ st.success(f"Se detectaron {len(bboxes)} rostros en la imagen.")
920
+ else:
921
+ st.warning("No se detectaron rostros. Prueba ajustar el umbral de confianza o usar otra imagen.")
922
+
923
  # Convert OpenCV image to PIL for download
924
  pil_img = Image.fromarray(processed_image[:, :, ::-1])
925
  st.markdown(
926
  get_image_download_link(pil_img, "face_detection_result.jpg", "📥 Download Processed Image"),
927
  unsafe_allow_html=True
928
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
929
 
930
  else: # Video mode
931
  # Video mode options
 
1111
  # File uploader for images
1112
  file_buffer = st.file_uploader("Upload an image", type=['jpg', 'jpeg', 'png'])
1113
 
1114
+ # Umbral de confianza ajustable
1115
+ conf_threshold = st.slider(
1116
+ "Umbral de confianza",
1117
+ min_value=0.05,
1118
+ max_value=0.95,
1119
+ value=0.2, # Valor por defecto más bajo (era 0.5)
1120
+ step=0.05,
1121
+ help="Ajusta este valor para controlar la sensibilidad de la detección facial. Un valor más bajo detecta más rostros pero puede tener falsos positivos."
1122
+ )
1123
+
1124
+ # Color del bounding box
1125
+ bbox_color_bgr = (0, 255, 0) # Verde brillante para mejor visibilidad
1126
+
1127
  if file_buffer is not None:
1128
  # Read the file and convert it to OpenCV format
1129
  raw_bytes = np.asarray(bytearray(file_buffer.read()), dtype=np.uint8)
 
1173
  st.subheader("Processed Image")
1174
  st.image(processed_image, channels='BGR', use_container_width=True)
1175
 
1176
+ # Mostrar mensaje sobre lo que se está viendo
1177
+ if len(bboxes) > 0:
1178
+ st.success(f"Se detectaron {len(bboxes)} rostros en la imagen.")
1179
+ else:
1180
+ st.warning("No se detectaron rostros. Prueba ajustar el umbral de confianza o usar otra imagen.")
1181
+
1182
  # Convert OpenCV image to PIL for download
1183
  pil_img = Image.fromarray(processed_image[:, :, ::-1])
1184
  st.markdown(