""" app.py — Identificador Caribicus warrenii (Hugging Face Spaces) Versión para servidor: con login (usuario/contraseña vía secretos del Space) y el modelo afinado. El cómputo ocurre en el Space, no en tu PC. """ import os import pandas as pd import gradio as gr import caribicus_finetuned as cf print("Cargando modelo afinado Caribicus...") try: cf._cargar_modelo() BASE = cf.cargar_base() U_CONF, U_DUD = cf.cargar_umbrales() N = len(BASE) OK = True print(f"Base: {N} individuos | Umbrales: {U_CONF}/{U_DUD}") except Exception as exc: BASE = {}; N = 0; OK = False; ERR = str(exc); U_CONF, U_DUD = 65.0, 50.0 print("ADVERTENCIA:", exc) COLOR = {'CONFIRMADO': '#27ae60', 'DUDOSO': '#e67e22', 'NUEVO': '#e74c3c'} ICONO = {'CONFIRMADO': '✅', 'DUDOSO': '⚠️', 'NUEVO': '❌'} ETIQ = {'CONFIRMADO': 'Confirmado', 'DUDOSO': 'Dudoso — requiere revisión manual', 'NUEVO': 'Nuevo individuo no registrado'} def _barra(pct, color, alto=10): return (f"
" f"
") def _html_resultado(estado, c1, p1, c2, p2): color = COLOR[estado] bloque2 = "" if c2: bloque2 = (f"
SEGUNDO CANDIDATO
" f"
" f"{c2}{p2:.1f} %
" f"{_barra(p2,'#95a5a6',7)}") return (f"
" f"
{ICONO[estado]}  {ETIQ[estado]}
" f"
" f"
MEJOR CANDIDATO
" f"
" f"{c1}" f"{p1:.1f} %
" f"{_barra(p1,color)}{bloque2}
") def predecir(imagen_path): if imagen_path is None: return "
Sube una foto y presiona Identificar.
", None if not OK: return f"
Error: {ERR}
", None try: emb = cf.foto_a_embedding(imagen_path, recortar=True) ranking = cf.identificar_embedding(emb, BASE) c1, p1 = ranking[0] c2, p2 = ranking[1] if len(ranking) > 1 else (None, 0.0) estado = cf.interpretar(p1, U_CONF, U_DUD) df = pd.DataFrame(ranking, columns=['Individuo', 'Confianza (%)']) df['Confianza (%)'] = df['Confianza (%)'].round(1) return _html_resultado(estado, c1, p1, c2, p2), df except Exception as exc: return f"
Error: {exc}
", None _sub = (f"**{N} individuos** · modelo afinado + recorte automático · " f"✅ ≥{U_CONF:.0f}% ⚠️ {U_DUD:.0f}–{U_CONF:.0f}% ❌ <{U_DUD:.0f}%" if OK else "⚠️ Error al cargar el modelo/base.") with gr.Blocks(title="Identificador Caribicus", theme=gr.themes.Soft()) as demo: gr.Markdown("# Identificador de Individuos — *Caribicus warrenii*") gr.Markdown(_sub) with gr.Row(): with gr.Column(scale=1): img_input = gr.Image(label="Foto a identificar", type="filepath", height=340) btn = gr.Button("Identificar", variant="primary", size="lg") with gr.Column(scale=1): html_out = gr.HTML(value="
Sube una foto y presiona Identificar.
") tabla_out = gr.Dataframe(headers=["Individuo", "Confianza (%)"], label="Ranking completo", interactive=False, wrap=False) btn.click(fn=predecir, inputs=img_input, outputs=[html_out, tabla_out]) gr.Markdown("La foto se recorta automáticamente (quita el fondo) antes de identificar.") # --- Login (usuario/contraseña desde los secretos del Space) --- _USER = os.environ.get("APP_USER", "equipo") _PASS = os.environ.get("APP_PASSWORD") # definido como secreto del Space _auth = (_USER, _PASS) if _PASS else None if __name__ == "__main__": demo.launch(auth=_auth)