Upload 2 files
Browse files- api_client.py +6 -0
- app.py +60 -0
api_client.py
CHANGED
|
@@ -482,6 +482,12 @@ def describe_image_with_svision(image_path: str, is_face: bool = True) -> Tuple[
|
|
| 482 |
|
| 483 |
full_description = result.strip() if result else ""
|
| 484 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 485 |
if not full_description:
|
| 486 |
return ("", "")
|
| 487 |
|
|
|
|
| 482 |
|
| 483 |
full_description = result.strip() if result else ""
|
| 484 |
|
| 485 |
+
# Limpiar prefijos no deseados como "user", "assistant", etc.
|
| 486 |
+
for prefix in ["user:", "user ", "assistant:", "assistant ", "User:", "User ", "Assistant:", "Assistant "]:
|
| 487 |
+
if full_description.startswith(prefix):
|
| 488 |
+
full_description = full_description[len(prefix):].strip()
|
| 489 |
+
break
|
| 490 |
+
|
| 491 |
if not full_description:
|
| 492 |
return ("", "")
|
| 493 |
|
app.py
CHANGED
|
@@ -514,8 +514,68 @@ if page == "Processar vídeo nou":
|
|
| 514 |
import tempfile
|
| 515 |
import requests as _req
|
| 516 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 517 |
# Mostrar progreso para el usuario
|
| 518 |
total_chars = len(chars)
|
|
|
|
|
|
|
|
|
|
| 519 |
progress_text = st.empty()
|
| 520 |
progress_bar = st.progress(0.0)
|
| 521 |
progress_text.info("🎨 Generant descripcions amb Salamandra Vision (pot trigar uns segons en la primera càrrega)...")
|
|
|
|
| 514 |
import tempfile
|
| 515 |
import requests as _req
|
| 516 |
|
| 517 |
+
# FILTRO CONSERVADOR: Eliminar falsos positivos de detección de caras
|
| 518 |
+
# Filosofía: En caso de duda, descartar. Prioridad = NO aceptar ninguna cara falsa.
|
| 519 |
+
chars_filtered = []
|
| 520 |
+
for ch in chars:
|
| 521 |
+
# Obtener información del bounding box (si existe)
|
| 522 |
+
bbox = ch.get("bbox", {})
|
| 523 |
+
count = ch.get("count", 0) # Número de detecciones en el cluster
|
| 524 |
+
|
| 525 |
+
# Criterios de filtrado ESTRICTOS:
|
| 526 |
+
# 1. Al menos 2 detecciones en el cluster (más robusto que 1)
|
| 527 |
+
# 2. Tamaño mínimo más conservador (50px en lugar de 30px)
|
| 528 |
+
# 3. Aspect ratio más restrictivo (0.6 - 1.5 en lugar de 0.5 - 2.0)
|
| 529 |
+
is_valid = True
|
| 530 |
+
rejection_reason = ""
|
| 531 |
+
|
| 532 |
+
# Criterio 1: Mínimo 2 detecciones para evitar outliers
|
| 533 |
+
if count < 2:
|
| 534 |
+
rejection_reason = f"count={count} < 2 (molt poques deteccions)"
|
| 535 |
+
is_valid = False
|
| 536 |
+
|
| 537 |
+
# Si hay bbox disponible, aplicar filtros adicionales ESTRICTOS
|
| 538 |
+
if bbox and is_valid:
|
| 539 |
+
w = bbox.get("width", 0)
|
| 540 |
+
h = bbox.get("height", 0)
|
| 541 |
+
|
| 542 |
+
# Criterio 2: Descartar caras pequeñas (< 50px) - más conservador
|
| 543 |
+
if w < 50 or h < 50:
|
| 544 |
+
rejection_reason = f"bbox massa petit ({w}x{h}px, mínim 50x50)"
|
| 545 |
+
is_valid = False
|
| 546 |
+
|
| 547 |
+
# Criterio 3: Aspect ratio MÁS restrictivo para caras (0.6 - 1.5)
|
| 548 |
+
# Las caras reales suelen tener proporciones más regulares
|
| 549 |
+
elif h > 0:
|
| 550 |
+
aspect_ratio = w / h
|
| 551 |
+
if aspect_ratio < 0.6 or aspect_ratio > 1.5:
|
| 552 |
+
rejection_reason = f"aspect ratio fora de rang ({aspect_ratio:.2f}, rang: 0.6-1.5)"
|
| 553 |
+
is_valid = False
|
| 554 |
+
|
| 555 |
+
# Criterio 4: Descartar caras extremadamente grandes (probablemente falsos positivos)
|
| 556 |
+
# Asumiendo que las caras no deberían ocupar más de 800px
|
| 557 |
+
elif w > 800 or h > 800:
|
| 558 |
+
rejection_reason = f"bbox massa gran ({w}x{h}px, màxim 800x800)"
|
| 559 |
+
is_valid = False
|
| 560 |
+
|
| 561 |
+
if is_valid:
|
| 562 |
+
chars_filtered.append(ch)
|
| 563 |
+
log(f"[FILTER] ✓ Cara acceptada: {ch.get('id', 'unknown')} (count={count}, bbox={bbox.get('width', 'N/A')}x{bbox.get('height', 'N/A')})")
|
| 564 |
+
else:
|
| 565 |
+
log(f"[FILTER] ✗ Descartant {ch.get('id', 'unknown')}: {rejection_reason}")
|
| 566 |
+
|
| 567 |
+
# Actualizar lista de personajes filtrados
|
| 568 |
+
chars = chars_filtered
|
| 569 |
+
log(f"[FILTER] Personatges després del filtre: {len(chars)}")
|
| 570 |
+
|
| 571 |
+
# Actualizar session_state con la lista filtrada
|
| 572 |
+
st.session_state.characters_detected = chars
|
| 573 |
+
|
| 574 |
# Mostrar progreso para el usuario
|
| 575 |
total_chars = len(chars)
|
| 576 |
+
if total_chars == 0:
|
| 577 |
+
st.warning("⚠️ No s'han detectat cares vàlides després del filtre de qualitat.")
|
| 578 |
+
|
| 579 |
progress_text = st.empty()
|
| 580 |
progress_bar = st.progress(0.0)
|
| 581 |
progress_text.info("🎨 Generant descripcions amb Salamandra Vision (pot trigar uns segons en la primera càrrega)...")
|