Spaces:
Sleeping
Sleeping
Upload 2 files
Browse files
app.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
import base64
|
|
|
|
| 2 |
import io
|
| 3 |
import json
|
| 4 |
import traceback
|
|
@@ -22,6 +23,7 @@ from transformers import (
|
|
| 22 |
CLIPProcessor,
|
| 23 |
SegformerImageProcessor,
|
| 24 |
SegformerForSemanticSegmentation,
|
|
|
|
| 25 |
)
|
| 26 |
from sam2.build_sam import build_sam2
|
| 27 |
from sam2.sam2_image_predictor import SAM2ImagePredictor
|
|
@@ -55,6 +57,7 @@ segformer_city_model = None
|
|
| 55 |
segformer_city_processor = None
|
| 56 |
segformer_ade_model = None
|
| 57 |
segformer_ade_processor = None
|
|
|
|
| 58 |
|
| 59 |
# --- CATÁLOGO CONTEXTUAL ---
|
| 60 |
CATALOGO_POR_ENTORNO = {
|
|
@@ -385,7 +388,7 @@ def autodetectar_entorno(imagen: Image.Image):
|
|
| 385 |
if imagen is None:
|
| 386 |
entorno_predicho = claves_entorno[0]
|
| 387 |
nuevas_opciones = list(CATALOGO_POR_ENTORNO[entorno_predicho].keys())
|
| 388 |
-
motor_seleccionado = "
|
| 389 |
return (
|
| 390 |
gr.update(value=entorno_predicho),
|
| 391 |
gr.update(choices=nuevas_opciones, value=nuevas_opciones),
|
|
@@ -405,7 +408,7 @@ def autodetectar_entorno(imagen: Image.Image):
|
|
| 405 |
|
| 406 |
entorno_detectado = claves_entorno[indice_ganador]
|
| 407 |
nuevas_opciones = list(CATALOGO_POR_ENTORNO[entorno_detectado].keys())
|
| 408 |
-
motor_seleccionado = "
|
| 409 |
|
| 410 |
return (
|
| 411 |
gr.update(value=entorno_detectado),
|
|
@@ -416,14 +419,43 @@ def autodetectar_entorno(imagen: Image.Image):
|
|
| 416 |
|
| 417 |
def segmentar_y_analizar(imagen: Image.Image, entorno: str, seleccion: list, umbral_sensibilidad: float, motor: str, usar_limpieza: bool):
|
| 418 |
print(f"\n--- Iniciando análisis con motor: {motor} ---")
|
|
|
|
| 419 |
|
| 420 |
-
if imagen is None or len(seleccion) == 0:
|
| 421 |
return None, "Sube una imagen y selecciona al menos un elemento.", None
|
| 422 |
|
| 423 |
imagen_rgb = imagen.convert("RGB")
|
| 424 |
imagen_np = np.array(imagen_rgb)
|
| 425 |
total_pixels = imagen.width * imagen.height
|
| 426 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 427 |
masks_finales, etiquetas_finales, debug_image = _run_engines_raw(
|
| 428 |
imagen_rgb, imagen_np, entorno, seleccion, umbral_sensibilidad, motor, usar_limpieza
|
| 429 |
)
|
|
@@ -522,23 +554,16 @@ def segment_for_backend(image_np: np.ndarray):
|
|
| 522 |
|
| 523 |
def seleccionar_motor_por_entorno(entorno):
|
| 524 |
exteriores = ["🏙️ Fachada / Exterior", "🌳 Terraza / Patio / Jardín"]
|
| 525 |
-
interiores = [
|
| 526 |
-
"🛋️ Interiores (Sala / Cuartos)",
|
| 527 |
-
"🛁 Baño / Cocina",
|
| 528 |
-
"🏢 Oficinas / Corporativo",
|
| 529 |
-
"🏪 Locales Comerciales / Restaurantes",
|
| 530 |
-
"🏭 Garaje / Bodega / Industrial"
|
| 531 |
-
]
|
| 532 |
if entorno in exteriores:
|
| 533 |
-
return gr.update(value="
|
| 534 |
-
if entorno in interiores:
|
| 535 |
-
return gr.update(value="SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1")
|
| 536 |
return gr.update(value="SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1")
|
| 537 |
|
| 538 |
|
| 539 |
def actualizar_opciones(entorno, motor):
|
| 540 |
opciones = list(CATALOGO_POR_ENTORNO[entorno].keys())
|
| 541 |
-
if motor
|
|
|
|
|
|
|
| 542 |
label = "2. Elementos (Detalles a buscar con DINO 🎯)"
|
| 543 |
else:
|
| 544 |
label = "2. Elementos"
|
|
@@ -554,11 +579,12 @@ def crear_app():
|
|
| 554 |
imagen_entrada = gr.Image(type="pil", label="Foto del Espacio")
|
| 555 |
motor = gr.Radio(
|
| 556 |
choices=[
|
| 557 |
-
"
|
| 558 |
"Híbrido Arquitectura (Cityscapes Grande + DINO Pequeño)",
|
|
|
|
| 559 |
"DINO + SAM 2.1 (Objetos Contables)"
|
| 560 |
],
|
| 561 |
-
value="
|
| 562 |
label="🧠 Motor de Inteligencia Artificial"
|
| 563 |
)
|
| 564 |
tipo_entorno = gr.Dropdown(choices=list(CATALOGO_POR_ENTORNO.keys()), value=list(CATALOGO_POR_ENTORNO.keys())[0], label="1. Entorno (Autodetectado 🪄)")
|
|
|
|
| 1 |
import base64
|
| 2 |
+
import hashlib
|
| 3 |
import io
|
| 4 |
import json
|
| 5 |
import traceback
|
|
|
|
| 23 |
CLIPProcessor,
|
| 24 |
SegformerImageProcessor,
|
| 25 |
SegformerForSemanticSegmentation,
|
| 26 |
+
pipeline as hf_pipeline,
|
| 27 |
)
|
| 28 |
from sam2.build_sam import build_sam2
|
| 29 |
from sam2.sam2_image_predictor import SAM2ImagePredictor
|
|
|
|
| 57 |
segformer_city_processor = None
|
| 58 |
segformer_ade_model = None
|
| 59 |
segformer_ade_processor = None
|
| 60 |
+
sam_vit_pipeline = None
|
| 61 |
|
| 62 |
# --- CATÁLOGO CONTEXTUAL ---
|
| 63 |
CATALOGO_POR_ENTORNO = {
|
|
|
|
| 388 |
if imagen is None:
|
| 389 |
entorno_predicho = claves_entorno[0]
|
| 390 |
nuevas_opciones = list(CATALOGO_POR_ENTORNO[entorno_predicho].keys())
|
| 391 |
+
motor_seleccionado = "SAM Auto (Exteriores - Sin Prompts)" if entorno_predicho in exteriores else "SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1"
|
| 392 |
return (
|
| 393 |
gr.update(value=entorno_predicho),
|
| 394 |
gr.update(choices=nuevas_opciones, value=nuevas_opciones),
|
|
|
|
| 408 |
|
| 409 |
entorno_detectado = claves_entorno[indice_ganador]
|
| 410 |
nuevas_opciones = list(CATALOGO_POR_ENTORNO[entorno_detectado].keys())
|
| 411 |
+
motor_seleccionado = "SAM Auto (Exteriores - Sin Prompts)" if entorno_detectado in exteriores else "SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1"
|
| 412 |
|
| 413 |
return (
|
| 414 |
gr.update(value=entorno_detectado),
|
|
|
|
| 419 |
|
| 420 |
def segmentar_y_analizar(imagen: Image.Image, entorno: str, seleccion: list, umbral_sensibilidad: float, motor: str, usar_limpieza: bool):
|
| 421 |
print(f"\n--- Iniciando análisis con motor: {motor} ---")
|
| 422 |
+
global sam_vit_pipeline
|
| 423 |
|
| 424 |
+
if imagen is None or (len(seleccion) == 0 and motor != "SAM Auto (Exteriores - Sin Prompts)"):
|
| 425 |
return None, "Sube una imagen y selecciona al menos un elemento.", None
|
| 426 |
|
| 427 |
imagen_rgb = imagen.convert("RGB")
|
| 428 |
imagen_np = np.array(imagen_rgb)
|
| 429 |
total_pixels = imagen.width * imagen.height
|
| 430 |
|
| 431 |
+
# ==========================================================
|
| 432 |
+
# MOTOR 4: SAM ViT-Huge AUTOMÁTICO (Sin prompts — Exteriores)
|
| 433 |
+
# ==========================================================
|
| 434 |
+
if motor == "SAM Auto (Exteriores - Sin Prompts)":
|
| 435 |
+
if sam_vit_pipeline is None:
|
| 436 |
+
print("Cargando SAM ViT-Huge pipeline (mask-generation, CPU)...")
|
| 437 |
+
sam_vit_pipeline = hf_pipeline(
|
| 438 |
+
"mask-generation",
|
| 439 |
+
model="facebook/sam-vit-huge",
|
| 440 |
+
device=-1,
|
| 441 |
+
)
|
| 442 |
+
|
| 443 |
+
resultado_sam = sam_vit_pipeline(imagen_rgb)
|
| 444 |
+
if isinstance(resultado_sam, list):
|
| 445 |
+
resultado_sam = resultado_sam[0]
|
| 446 |
+
|
| 447 |
+
all_masks = resultado_sam.get("masks", [])
|
| 448 |
+
|
| 449 |
+
img_arr = np.array(imagen_rgb).copy()
|
| 450 |
+
overlay = img_arr.copy()
|
| 451 |
+
for i, mask in enumerate(all_masks):
|
| 452 |
+
hex_digest = hashlib.md5(str(i).encode()).hexdigest()[:6]
|
| 453 |
+
color = (int(hex_digest[0:2], 16), int(hex_digest[2:4], 16), int(hex_digest[4:6], 16))
|
| 454 |
+
overlay[np.array(mask) > 0] = color
|
| 455 |
+
|
| 456 |
+
blended = cv2.addWeighted(img_arr, 0.5, overlay, 0.5, 0)
|
| 457 |
+
return Image.fromarray(blended), f"📊 REPORTE (SAM Auto):<br>• {len(all_masks)} zonas detectadas automáticamente", None
|
| 458 |
+
|
| 459 |
masks_finales, etiquetas_finales, debug_image = _run_engines_raw(
|
| 460 |
imagen_rgb, imagen_np, entorno, seleccion, umbral_sensibilidad, motor, usar_limpieza
|
| 461 |
)
|
|
|
|
| 554 |
|
| 555 |
def seleccionar_motor_por_entorno(entorno):
|
| 556 |
exteriores = ["🏙️ Fachada / Exterior", "🌳 Terraza / Patio / Jardín"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
if entorno in exteriores:
|
| 558 |
+
return gr.update(value="SAM Auto (Exteriores - Sin Prompts)")
|
|
|
|
|
|
|
| 559 |
return gr.update(value="SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1")
|
| 560 |
|
| 561 |
|
| 562 |
def actualizar_opciones(entorno, motor):
|
| 563 |
opciones = list(CATALOGO_POR_ENTORNO[entorno].keys())
|
| 564 |
+
if motor == "SAM Auto (Exteriores - Sin Prompts)":
|
| 565 |
+
label = "2. Elementos (No aplica — detección totalmente automática ✨)"
|
| 566 |
+
elif motor in ["Híbrido Arquitectura (Cityscapes Grande + DINO Pequeño)", "SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1"]:
|
| 567 |
label = "2. Elementos (Detalles a buscar con DINO 🎯)"
|
| 568 |
else:
|
| 569 |
label = "2. Elementos"
|
|
|
|
| 579 |
imagen_entrada = gr.Image(type="pil", label="Foto del Espacio")
|
| 580 |
motor = gr.Radio(
|
| 581 |
choices=[
|
| 582 |
+
"SAM Auto (Exteriores - Sin Prompts)",
|
| 583 |
"Híbrido Arquitectura (Cityscapes Grande + DINO Pequeño)",
|
| 584 |
+
"SegFormer (SegFormer ADE20K+ DINO) + SAM 2.1",
|
| 585 |
"DINO + SAM 2.1 (Objetos Contables)"
|
| 586 |
],
|
| 587 |
+
value="SAM Auto (Exteriores - Sin Prompts)",
|
| 588 |
label="🧠 Motor de Inteligencia Artificial"
|
| 589 |
)
|
| 590 |
tipo_entorno = gr.Dropdown(choices=list(CATALOGO_POR_ENTORNO.keys()), value=list(CATALOGO_POR_ENTORNO.keys())[0], label="1. Entorno (Autodetectado 🪄)")
|