Spaces:
Build error
Build error
Commit
·
33bb295
1
Parent(s):
a0de189
Corregir error OpenCV de resize en detección de rostros
Browse files- streamlit_app.py +96 -38
streamlit_app.py
CHANGED
|
@@ -114,45 +114,75 @@ def main():
|
|
| 114 |
|
| 115 |
# Function for detecting faces in an image
|
| 116 |
def detect_face_dnn(net, frame, conf_threshold=0.5):
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
frame_w = frame.shape[1]
|
| 125 |
-
|
| 126 |
-
for i in range(detections.shape[2]):
|
| 127 |
-
confidence = detections[0, 0, i, 2]
|
| 128 |
-
if confidence > conf_threshold:
|
| 129 |
-
x1 = int(detections[0, 0, i, 3] * frame_w)
|
| 130 |
-
y1 = int(detections[0, 0, i, 4] * frame_h)
|
| 131 |
-
x2 = int(detections[0, 0, i, 5] * frame_w)
|
| 132 |
-
y2 = int(detections[0, 0, i, 6] * frame_h)
|
| 133 |
-
|
| 134 |
-
# Asegurarse de que las coordenadas estén dentro de los límites de la imagen
|
| 135 |
-
x1 = max(0, min(x1, frame_w - 1))
|
| 136 |
-
y1 = max(0, min(y1, frame_h - 1))
|
| 137 |
-
x2 = max(0, min(x2, frame_w - 1))
|
| 138 |
-
y2 = max(0, min(y2, frame_h - 1))
|
| 139 |
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
|
| 145 |
# Function for processing face detections
|
| 146 |
def process_face_detections(frame, detections, conf_threshold=0.5, bbox_color=(0, 255, 0)):
|
| 147 |
# Create a copy for drawing on
|
| 148 |
result_frame = frame.copy()
|
| 149 |
|
| 150 |
-
#
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
# Dibujar el bounding box
|
| 157 |
cv2.rectangle(result_frame, (x1, y1), (x2, y2), bbox_color, 2)
|
| 158 |
|
|
@@ -162,6 +192,20 @@ def main():
|
|
| 162 |
|
| 163 |
# Añadir a la lista de bounding boxes
|
| 164 |
bboxes.append([x1, y1, x2, y2, confidence])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
|
| 166 |
return result_frame, bboxes
|
| 167 |
|
|
@@ -2171,13 +2215,21 @@ def main():
|
|
| 2171 |
return av.VideoFrame.from_ndarray(img, format="bgr24")
|
| 2172 |
|
| 2173 |
try:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2174 |
# Reducir tamaño del frame para procesamiento más rápido
|
| 2175 |
scale_factor = 0.5
|
| 2176 |
-
|
|
|
|
| 2177 |
|
| 2178 |
-
# Detect faces
|
| 2179 |
-
|
| 2180 |
-
_, bboxes = process_face_detections(small_img, detections, confidence_threshold)
|
| 2181 |
|
| 2182 |
# Ajustar bounding boxes al tamaño original
|
| 2183 |
original_bboxes = []
|
|
@@ -2216,8 +2268,14 @@ def main():
|
|
| 2216 |
return av.VideoFrame.from_ndarray(result_frame, format="bgr24")
|
| 2217 |
|
| 2218 |
except Exception as e:
|
| 2219 |
-
|
| 2220 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2221 |
|
| 2222 |
# Display WebRTC streamer
|
| 2223 |
webrtc_ctx = webrtc_streamer(
|
|
|
|
| 114 |
|
| 115 |
# Function for detecting faces in an image
|
| 116 |
def detect_face_dnn(net, frame, conf_threshold=0.5):
|
| 117 |
+
"""
|
| 118 |
+
Detecta rostros usando el modelo DNN y devuelve las detecciones.
|
| 119 |
+
"""
|
| 120 |
+
try:
|
| 121 |
+
# Verificar que el frame sea válido
|
| 122 |
+
if frame is None or frame.size == 0 or frame.shape[0] == 0 or frame.shape[1] == 0:
|
| 123 |
+
return []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
+
# Crear blob a partir del frame (redimensionar a 300x300, escalar, etc.)
|
| 126 |
+
blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), [104, 117, 123], False, False)
|
| 127 |
+
|
| 128 |
+
# Establecer la entrada para la red neuronal
|
| 129 |
+
net.setInput(blob)
|
| 130 |
+
|
| 131 |
+
# Realizar la detección
|
| 132 |
+
detections = net.forward()
|
| 133 |
+
|
| 134 |
+
# Procesar las detecciones para devolver una lista de bounding boxes
|
| 135 |
+
bboxes = []
|
| 136 |
+
frame_h = frame.shape[0]
|
| 137 |
+
frame_w = frame.shape[1]
|
| 138 |
+
|
| 139 |
+
for i in range(detections.shape[2]):
|
| 140 |
+
confidence = detections[0, 0, i, 2]
|
| 141 |
+
if confidence > conf_threshold:
|
| 142 |
+
x1 = int(detections[0, 0, i, 3] * frame_w)
|
| 143 |
+
y1 = int(detections[0, 0, i, 4] * frame_h)
|
| 144 |
+
x2 = int(detections[0, 0, i, 5] * frame_w)
|
| 145 |
+
y2 = int(detections[0, 0, i, 6] * frame_h)
|
| 146 |
+
|
| 147 |
+
# Asegurarse de que las coordenadas estén dentro de los límites
|
| 148 |
+
x1 = max(0, min(x1, frame_w - 1))
|
| 149 |
+
y1 = max(0, min(y1, frame_h - 1))
|
| 150 |
+
x2 = max(0, min(x2, frame_w - 1))
|
| 151 |
+
y2 = max(0, min(y2, frame_h - 1))
|
| 152 |
+
|
| 153 |
+
# Añadir el bounding box y la confianza
|
| 154 |
+
bboxes.append([x1, y1, x2, y2, confidence])
|
| 155 |
+
|
| 156 |
+
return bboxes
|
| 157 |
+
except Exception as e:
|
| 158 |
+
st.error(f"Error en la detección de rostros: {e}")
|
| 159 |
+
return []
|
| 160 |
|
| 161 |
# Function for processing face detections
|
| 162 |
def process_face_detections(frame, detections, conf_threshold=0.5, bbox_color=(0, 255, 0)):
|
| 163 |
# Create a copy for drawing on
|
| 164 |
result_frame = frame.copy()
|
| 165 |
|
| 166 |
+
# Procesar detecciones si son del formato original
|
| 167 |
+
if isinstance(detections, np.ndarray) and len(detections.shape) == 4:
|
| 168 |
+
bboxes = []
|
| 169 |
+
frame_h = frame.shape[0]
|
| 170 |
+
frame_w = frame.shape[1]
|
| 171 |
+
|
| 172 |
+
for i in range(detections.shape[2]):
|
| 173 |
+
confidence = detections[0, 0, i, 2]
|
| 174 |
+
if confidence > conf_threshold:
|
| 175 |
+
x1 = int(detections[0, 0, i, 3] * frame_w)
|
| 176 |
+
y1 = int(detections[0, 0, i, 4] * frame_h)
|
| 177 |
+
x2 = int(detections[0, 0, i, 5] * frame_w)
|
| 178 |
+
y2 = int(detections[0, 0, i, 6] * frame_h)
|
| 179 |
+
|
| 180 |
+
# Asegurarse de que las coordenadas estén dentro de los límites
|
| 181 |
+
x1 = max(0, min(x1, frame_w - 1))
|
| 182 |
+
y1 = max(0, min(y1, frame_h - 1))
|
| 183 |
+
x2 = max(0, min(x2, frame_w - 1))
|
| 184 |
+
y2 = max(0, min(y2, frame_h - 1))
|
| 185 |
+
|
| 186 |
# Dibujar el bounding box
|
| 187 |
cv2.rectangle(result_frame, (x1, y1), (x2, y2), bbox_color, 2)
|
| 188 |
|
|
|
|
| 192 |
|
| 193 |
# Añadir a la lista de bounding boxes
|
| 194 |
bboxes.append([x1, y1, x2, y2, confidence])
|
| 195 |
+
else:
|
| 196 |
+
# Si ya es una lista de bounding boxes (formato nuevo)
|
| 197 |
+
bboxes = detections
|
| 198 |
+
# Dibujar bounding boxes
|
| 199 |
+
for bbox in bboxes:
|
| 200 |
+
if len(bbox) == 5: # Asegurarse de que el bounding box tiene el formato correcto
|
| 201 |
+
x1, y1, x2, y2, confidence = bbox
|
| 202 |
+
if confidence >= conf_threshold:
|
| 203 |
+
# Dibujar el bounding box
|
| 204 |
+
cv2.rectangle(result_frame, (x1, y1), (x2, y2), bbox_color, 2)
|
| 205 |
+
|
| 206 |
+
# Añadir texto con la confianza
|
| 207 |
+
label = f"{confidence:.2f}"
|
| 208 |
+
cv2.putText(result_frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, bbox_color, 2)
|
| 209 |
|
| 210 |
return result_frame, bboxes
|
| 211 |
|
|
|
|
| 2215 |
return av.VideoFrame.from_ndarray(img, format="bgr24")
|
| 2216 |
|
| 2217 |
try:
|
| 2218 |
+
# Verificar que la imagen no sea nula
|
| 2219 |
+
if img is None or img.size == 0 or img.shape[0] == 0 or img.shape[1] == 0:
|
| 2220 |
+
# Si la imagen es inválida, devolver un frame en blanco
|
| 2221 |
+
blank_frame = np.ones((480, 640, 3), dtype=np.uint8) * 255
|
| 2222 |
+
cv2.putText(blank_frame, "Error: Invalid frame", (50, 240),
|
| 2223 |
+
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
|
| 2224 |
+
return av.VideoFrame.from_ndarray(blank_frame, format="bgr24")
|
| 2225 |
+
|
| 2226 |
# Reducir tamaño del frame para procesamiento más rápido
|
| 2227 |
scale_factor = 0.5
|
| 2228 |
+
h, w = img.shape[:2]
|
| 2229 |
+
small_img = cv2.resize(img, (int(w * scale_factor), int(h * scale_factor)))
|
| 2230 |
|
| 2231 |
+
# Detect faces - la función ahora devuelve directamente los bboxes
|
| 2232 |
+
bboxes = detect_face_dnn(face_net, small_img, confidence_threshold)
|
|
|
|
| 2233 |
|
| 2234 |
# Ajustar bounding boxes al tamaño original
|
| 2235 |
original_bboxes = []
|
|
|
|
| 2268 |
return av.VideoFrame.from_ndarray(result_frame, format="bgr24")
|
| 2269 |
|
| 2270 |
except Exception as e:
|
| 2271 |
+
# En caso de cualquier error, mostrar mensaje en la imagen
|
| 2272 |
+
error_frame = np.ones((480, 640, 3), dtype=np.uint8) * 255
|
| 2273 |
+
error_msg = f"Error: {str(e)}"
|
| 2274 |
+
cv2.putText(error_frame, error_msg[:50], (20, 240),
|
| 2275 |
+
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
|
| 2276 |
+
cv2.putText(error_frame, "Intente usar opciones alternativas", (20, 280),
|
| 2277 |
+
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
|
| 2278 |
+
return av.VideoFrame.from_ndarray(error_frame, format="bgr24")
|
| 2279 |
|
| 2280 |
# Display WebRTC streamer
|
| 2281 |
webrtc_ctx = webrtc_streamer(
|