---
name: build_relief_glb_from_image
kind: pipeline
lang: py
domain: pipelines
version: "1.0.0"
purity: impure
signature: "def build_relief_glb_from_image(image_path: str, out_glb_path: str, model_name: str = 'depth-anything/Depth-Anything-V2-Small-hf', device: str = 'auto', z_scale: float = 0.35, max_dim: int = 220) -> dict"
description: "Pipeline one-shot imagen 2D -> .glb de relieve texturizado. Compone estimate_image_depth (profundidad monocular Depth-Anything-V2) + depth_to_relief_glb (malla heightmap + textura) en una sola llamada. Promueve a un paso la secuencia que img_to_3d_webapp hacia en dos (issue 0087). Grupo img-to-3d."
tags: [img-to-3d, pipelines, depth, glb, gltf, mesh, relief, 3d, computer-vision, launcher]
uses_functions: [estimate_image_depth_py_datascience, depth_to_relief_glb_py_datascience]
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
  - name: image_path
    desc: "Ruta a la imagen de entrada (cualquier formato que PIL abra). Si no existe vuelve {status:error, stage:estimate}."
  - name: out_glb_path
    desc: "Ruta de salida del .glb. Su directorio padre debe existir o falla en la etapa relief (status error)."
  - name: model_name
    desc: "Id de modelo HuggingFace de depth-estimation. Default Depth-Anything-V2-Small-hf (rapido)."
  - name: device
    desc: "'auto' (GPU0 si hay), 'cpu', o indice/cadena cuda. Ver gotchas de estimate_image_depth para el detalle de 'cuda:N' vs indice entero."
  - name: z_scale
    desc: "Amplitud del relieve como fraccion del lado de la malla (default 0.35). Mayor = relieve mas exagerado."
  - name: max_dim
    desc: "Lado maximo del grid tras downsample (default 220, ~36k-48k vertices segun aspect ratio). Controla detalle vs peso del .glb."
output: "dict. Exito: {status:'ok', glb_path:str, vertices:int, faces:int, height:int, width:int, model:str, device:str}. Error: {status:'error', stage:'estimate'|'relief', error:str}. No lanza. Salida JSON-serializable (sin ndarray ni PIL), apta para `fn run`."
tested: false
tests: []
test_file_path: ""
file_path: "python/functions/pipelines/build_relief_glb_from_image.py"
---

## Ejemplo

```bash
# Requiere venv con torch + transformers + trimesh + pillow + numpy (p.ej. apps/img_to_3d_webapp/backend/.venv).
./fn run build_relief_glb_from_image_py_pipelines apps/img_to_3d_webapp/samples/cats.jpg /tmp/cats_relief.glb
# {"status": "ok", "glb_path": "/tmp/cats_relief.glb", "vertices": 36300, "faces": 71832, "height": 165, "width": 220, "model": "...", "device": "auto"}
```

Como import (composicion en codigo):

```python
import sys
sys.path.insert(0, "python/functions/pipelines")
from build_relief_glb_from_image import build_relief_glb_from_image

res = build_relief_glb_from_image("apps/img_to_3d_webapp/samples/cats.jpg", "/tmp/cats_relief.glb")
print(res["status"], res["vertices"], res["faces"])   # ok 36300 71832
```

## Cuando usarla

Cuando quieras el modelo 3D (.glb) directamente desde una imagen y NO necesites el mapa de
profundidad intermedio para otra cosa. Es el atajo del grupo `img-to-3d`: una sola llamada en vez
de orquestar `estimate_image_depth` + `depth_to_relief_glb` a mano. Si necesitas el `depth` por
separado (para inspeccionarlo, reusarlo, o aplicar otra reconstruccion), llama a las dos funciones
sueltas en su lugar.

## Gotchas

- **Impuro (pipeline)**: carga modelo HuggingFace (descarga pesos la 1a vez), usa GPU/CPU y
  escribe el .glb en disco. Hereda todos los gotchas de `estimate_image_depth_py_datascience` y
  `depth_to_relief_glb_py_datascience` (estado de proceso del pipeline cacheado, profundidad
  relativa, relieve 2.5D, directorio de salida debe existir).
- **Deps de vision**: requiere `torch`+`transformers`+`trimesh`+`pillow`+`numpy`. Importa las dos
  funciones del registry de forma PLANA (anade `python/functions/datascience` a `sys.path`) para
  NO arrastrar el `datascience.__init__` (que trae bs4/duckdb de otros dominios). Por eso `fn run`
  de este pipeline corre limpio en el venv de vision sin necesitar las deps de los scrapers.
- **stage en el error**: el campo `stage` (`estimate` o `relief`) indica en cual de los dos pasos
  fallo, util para depurar (p.ej. ruta de imagen mala -> stage estimate; dir de salida inexistente
  -> stage relief).
- Tag `launcher`: aparece en el Pipeline Launcher TUI; es un subproceso one-shot (no interactivo).
