Spaces:
Running
Running
Commit
·
ef29226
1
Parent(s):
44a87dc
fix: [Lunes 25/03/2024 15:30] Mejorada la detección de ojos y sonrisas - Optimización de parámetros y regiones de interés
Browse files- streamlit_app.py +47 -143
streamlit_app.py
CHANGED
|
@@ -174,8 +174,6 @@ def main():
|
|
| 174 |
|
| 175 |
for bbox in bboxes:
|
| 176 |
x1, y1, x2, y2, _ = bbox
|
| 177 |
-
roi_gray = gray[y1:y2, x1:x2]
|
| 178 |
-
roi_color = result_frame[y1:y2, x1:x2]
|
| 179 |
face_width = x2 - x1
|
| 180 |
face_height = y2 - y1
|
| 181 |
|
|
@@ -183,170 +181,76 @@ def main():
|
|
| 183 |
if detect_eyes:
|
| 184 |
# Adjust region of interest to focus on the upper part of the face
|
| 185 |
upper_face_y1 = y1
|
| 186 |
-
upper_face_y2 = y1 + int(face_height * 0.
|
| 187 |
|
| 188 |
-
#
|
| 189 |
-
|
|
|
|
| 190 |
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
# Split the upper region into two halves (left and right) to search for eyes individually
|
| 196 |
-
mid_x = x1 + face_width // 2
|
| 197 |
-
left_eye_roi_gray = gray[upper_face_y1:upper_face_y2, x1:mid_x]
|
| 198 |
-
right_eye_roi_gray = gray[upper_face_y1:upper_face_y2, mid_x:x2]
|
| 199 |
-
|
| 200 |
-
left_eye_roi_color = result_frame[upper_face_y1:upper_face_y2, x1:mid_x]
|
| 201 |
-
right_eye_roi_color = result_frame[upper_face_y1:upper_face_y2, mid_x:x2]
|
| 202 |
-
|
| 203 |
-
# Apply histogram equalization and contrast enhancement for all regions
|
| 204 |
-
if upper_face_roi_gray.size > 0:
|
| 205 |
-
upper_face_roi_gray = cv2.equalizeHist(upper_face_roi_gray)
|
| 206 |
-
|
| 207 |
-
# Enhance contrast
|
| 208 |
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
|
| 209 |
-
|
| 210 |
|
| 211 |
-
#
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
scaleFactor=1.
|
| 215 |
-
minNeighbors=max(
|
| 216 |
-
minSize=(int(face_width * 0.
|
| 217 |
-
maxSize=(int(face_width * 0.
|
| 218 |
)
|
| 219 |
|
| 220 |
-
#
|
| 221 |
-
if len(
|
| 222 |
-
# Sort by size
|
| 223 |
-
|
| 224 |
-
|
| 225 |
|
| 226 |
-
for ex, ey, ew, eh in
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
cv2.putText(upper_face_roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
|
| 230 |
-
else:
|
| 231 |
-
# If no eyes found in full region, try left and right separately
|
| 232 |
-
if left_eye_roi_gray.size > 0:
|
| 233 |
-
left_eye_roi_gray = cv2.equalizeHist(left_eye_roi_gray)
|
| 234 |
-
left_eye_roi_gray = clahe.apply(left_eye_roi_gray)
|
| 235 |
-
|
| 236 |
-
left_eyes = eye_cascade.detectMultiScale(
|
| 237 |
-
left_eye_roi_gray,
|
| 238 |
-
scaleFactor=1.03,
|
| 239 |
-
minNeighbors=max(1, eye_sensitivity-2),
|
| 240 |
-
minSize=(int(face_width * 0.08), int(face_width * 0.08)),
|
| 241 |
-
maxSize=(int(face_width * 0.25), int(face_width * 0.25))
|
| 242 |
-
)
|
| 243 |
-
|
| 244 |
-
if len(left_eyes) > 0:
|
| 245 |
-
# Sort by size and take the largest
|
| 246 |
-
left_eyes = sorted(left_eyes, key=lambda e: e[2] * e[3], reverse=True)
|
| 247 |
-
left_eye = left_eyes[0]
|
| 248 |
eye_count += 1
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
ex, ey, ew, eh = left_eye
|
| 252 |
-
cv2.rectangle(left_eye_roi_color, (ex, ey), (ex+ew, ey+eh), (255, 0, 0), 2)
|
| 253 |
-
cv2.putText(left_eye_roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
|
| 254 |
-
|
| 255 |
-
if right_eye_roi_gray.size > 0:
|
| 256 |
-
right_eye_roi_gray = cv2.equalizeHist(right_eye_roi_gray)
|
| 257 |
-
right_eye_roi_gray = clahe.apply(right_eye_roi_gray)
|
| 258 |
-
|
| 259 |
-
right_eyes = eye_cascade.detectMultiScale(
|
| 260 |
-
right_eye_roi_gray,
|
| 261 |
-
scaleFactor=1.03,
|
| 262 |
-
minNeighbors=max(1, eye_sensitivity-2),
|
| 263 |
-
minSize=(int(face_width * 0.08), int(face_width * 0.08)),
|
| 264 |
-
maxSize=(int(face_width * 0.25), int(face_width * 0.25))
|
| 265 |
-
)
|
| 266 |
-
|
| 267 |
-
if len(right_eyes) > 0:
|
| 268 |
-
# Sort by size and take the largest
|
| 269 |
-
right_eyes = sorted(right_eyes, key=lambda e: e[2] * e[3], reverse=True)
|
| 270 |
-
right_eye = right_eyes[0]
|
| 271 |
-
eye_count += 1
|
| 272 |
-
|
| 273 |
-
# Draw rectangle for the right eye
|
| 274 |
-
ex, ey, ew, eh = right_eye
|
| 275 |
-
cv2.rectangle(right_eye_roi_color, (ex, ey), (ex+ew, ey+eh), (255, 0, 0), 2)
|
| 276 |
-
cv2.putText(right_eye_roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
|
| 277 |
|
| 278 |
# Detect smile if enabled
|
| 279 |
if detect_smile:
|
| 280 |
-
#
|
| 281 |
-
#
|
|
|
|
| 282 |
|
| 283 |
-
#
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
lower_face_roi_color = result_frame[lower_face_y1:y2, x1:x2]
|
| 287 |
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
# Apply histogram equalization and enhance contrast
|
| 293 |
-
smile_detected = False
|
| 294 |
-
|
| 295 |
-
if lower_face_roi_gray.size > 0:
|
| 296 |
-
lower_face_roi_gray = cv2.equalizeHist(lower_face_roi_gray)
|
| 297 |
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
|
| 298 |
-
|
| 299 |
|
| 300 |
-
#
|
| 301 |
smiles = smile_cascade.detectMultiScale(
|
| 302 |
-
|
| 303 |
-
scaleFactor=1.
|
| 304 |
-
minNeighbors=smile_sensitivity,
|
| 305 |
-
minSize=(int(face_width * 0.
|
| 306 |
-
maxSize=(int(face_width * 0.
|
| 307 |
)
|
| 308 |
|
|
|
|
| 309 |
if len(smiles) > 0:
|
| 310 |
# Sort by size and take the largest
|
| 311 |
smiles = sorted(smiles, key=lambda s: s[2] * s[3], reverse=True)
|
| 312 |
sx, sy, sw, sh = smiles[0]
|
| 313 |
|
| 314 |
-
#
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
cv2.rectangle(lower_face_roi_color, (sx, sy), (sx+sw, sy+sh), (0, 0, 255), 2)
|
| 320 |
-
cv2.putText(lower_face_roi_color, "Smile", (sx, sy-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
|
| 321 |
-
|
| 322 |
-
# If no smile detected in standard region, try alternative region
|
| 323 |
-
if not smile_detected and alt_lower_face_roi_gray.size > 0:
|
| 324 |
-
alt_lower_face_roi_gray = cv2.equalizeHist(alt_lower_face_roi_gray)
|
| 325 |
-
alt_lower_face_roi_gray = clahe.apply(alt_lower_face_roi_gray)
|
| 326 |
-
|
| 327 |
-
# Try with more sensitive parameters
|
| 328 |
-
alt_smiles = smile_cascade.detectMultiScale(
|
| 329 |
-
alt_lower_face_roi_gray,
|
| 330 |
-
scaleFactor=1.1,
|
| 331 |
-
minNeighbors=max(1, smile_sensitivity-5), # More sensitive
|
| 332 |
-
minSize=(int(face_width * 0.2), int(face_width * 0.1)),
|
| 333 |
-
maxSize=(int(face_width * 0.6), int(face_width * 0.3))
|
| 334 |
-
)
|
| 335 |
-
|
| 336 |
-
if len(alt_smiles) > 0:
|
| 337 |
-
# Sort by size and take the largest
|
| 338 |
-
alt_smiles = sorted(alt_smiles, key=lambda s: s[2] * s[3], reverse=True)
|
| 339 |
-
sx, sy, sw, sh = alt_smiles[0]
|
| 340 |
-
|
| 341 |
-
# Adjust coordinates for the alternative region
|
| 342 |
-
adjusted_sy = sy + (alt_lower_face_y1 - lower_face_y1)
|
| 343 |
-
|
| 344 |
-
# Increment smile counter
|
| 345 |
-
smile_count += 1
|
| 346 |
-
|
| 347 |
-
# Draw rectangle for the smile (in the original lower face ROI)
|
| 348 |
-
cv2.rectangle(lower_face_roi_color, (sx, adjusted_sy), (sx+sw, adjusted_sy+sh), (0, 0, 255), 2)
|
| 349 |
-
cv2.putText(lower_face_roi_color, "Smile", (sx, adjusted_sy-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
|
| 350 |
|
| 351 |
return result_frame, eye_count, smile_count
|
| 352 |
|
|
|
|
| 174 |
|
| 175 |
for bbox in bboxes:
|
| 176 |
x1, y1, x2, y2, _ = bbox
|
|
|
|
|
|
|
| 177 |
face_width = x2 - x1
|
| 178 |
face_height = y2 - y1
|
| 179 |
|
|
|
|
| 181 |
if detect_eyes:
|
| 182 |
# Adjust region of interest to focus on the upper part of the face
|
| 183 |
upper_face_y1 = y1
|
| 184 |
+
upper_face_y2 = y1 + int(face_height * 0.45) # Reduced to focus more on the eye area
|
| 185 |
|
| 186 |
+
# Extract ROI for eyes
|
| 187 |
+
eye_roi_gray = gray[upper_face_y1:upper_face_y2, x1:x2]
|
| 188 |
+
eye_roi_color = result_frame[upper_face_y1:upper_face_y2, x1:x2]
|
| 189 |
|
| 190 |
+
if eye_roi_gray.size > 0:
|
| 191 |
+
# Enhance contrast for better detection
|
| 192 |
+
eye_roi_gray = cv2.equalizeHist(eye_roi_gray)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
|
| 194 |
+
eye_roi_gray = clahe.apply(eye_roi_gray)
|
| 195 |
|
| 196 |
+
# Detect eyes with adjusted parameters
|
| 197 |
+
eyes = eye_cascade.detectMultiScale(
|
| 198 |
+
eye_roi_gray,
|
| 199 |
+
scaleFactor=1.05,
|
| 200 |
+
minNeighbors=max(3, eye_sensitivity),
|
| 201 |
+
minSize=(int(face_width * 0.1), int(face_width * 0.1)),
|
| 202 |
+
maxSize=(int(face_width * 0.25), int(face_width * 0.25))
|
| 203 |
)
|
| 204 |
|
| 205 |
+
# Process detected eyes
|
| 206 |
+
if len(eyes) > 0:
|
| 207 |
+
# Sort by size and position
|
| 208 |
+
eyes = sorted(eyes, key=lambda e: (e[2] * e[3], -e[1])) # Sort by size and vertical position
|
| 209 |
+
eyes = eyes[:2] # Take at most 2 largest eyes
|
| 210 |
|
| 211 |
+
for (ex, ey, ew, eh) in eyes:
|
| 212 |
+
# Validate eye size and position
|
| 213 |
+
if ew * eh > (face_width * face_height * 0.01): # Minimum size threshold
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 214 |
eye_count += 1
|
| 215 |
+
cv2.rectangle(eye_roi_color, (ex, ey), (ex+ew, ey+eh), (255, 0, 0), 2)
|
| 216 |
+
cv2.putText(eye_roi_color, "Eye", (ex, ey-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
|
| 218 |
# Detect smile if enabled
|
| 219 |
if detect_smile:
|
| 220 |
+
# Adjust region of interest for smile detection
|
| 221 |
+
lower_face_y1 = y1 + int(face_height * 0.5) # Start from middle of face
|
| 222 |
+
lower_face_y2 = y2
|
| 223 |
|
| 224 |
+
# Extract ROI for smile
|
| 225 |
+
smile_roi_gray = gray[lower_face_y1:lower_face_y2, x1:x2]
|
| 226 |
+
smile_roi_color = result_frame[lower_face_y1:lower_face_y2, x1:x2]
|
|
|
|
| 227 |
|
| 228 |
+
if smile_roi_gray.size > 0:
|
| 229 |
+
# Enhance contrast for better detection
|
| 230 |
+
smile_roi_gray = cv2.equalizeHist(smile_roi_gray)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
|
| 232 |
+
smile_roi_gray = clahe.apply(smile_roi_gray)
|
| 233 |
|
| 234 |
+
# Detect smiles with adjusted parameters
|
| 235 |
smiles = smile_cascade.detectMultiScale(
|
| 236 |
+
smile_roi_gray,
|
| 237 |
+
scaleFactor=1.1,
|
| 238 |
+
minNeighbors=max(5, smile_sensitivity),
|
| 239 |
+
minSize=(int(face_width * 0.3), int(face_width * 0.15)),
|
| 240 |
+
maxSize=(int(face_width * 0.6), int(face_width * 0.3))
|
| 241 |
)
|
| 242 |
|
| 243 |
+
# Process detected smiles
|
| 244 |
if len(smiles) > 0:
|
| 245 |
# Sort by size and take the largest
|
| 246 |
smiles = sorted(smiles, key=lambda s: s[2] * s[3], reverse=True)
|
| 247 |
sx, sy, sw, sh = smiles[0]
|
| 248 |
|
| 249 |
+
# Validate smile size and position
|
| 250 |
+
if sw * sh > (face_width * face_height * 0.05): # Minimum size threshold
|
| 251 |
+
smile_count += 1
|
| 252 |
+
cv2.rectangle(smile_roi_color, (sx, sy), (sx+sw, sy+sh), (0, 0, 255), 2)
|
| 253 |
+
cv2.putText(smile_roi_color, "Smile", (sx, sy-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 254 |
|
| 255 |
return result_frame, eye_count, smile_count
|
| 256 |
|