Files
fn_registry/docs/capabilities/img-to-3d.md
T
egutierrez 3cf8b21fea feat(datascience): promover remove_background al registry + mask en depth_to_relief_glb (grupo img-to-3d)
Completa la promoción del flujo imagen->3D al registry (grupo de capacidad
img-to-3d), extraído de la app img_to_3d_webapp.

- remove_background_py_datascience (nueva): elimina el fondo con cascada
  rembg/U2Net -> OpenCV GrabCut -> umbral NumPy, compone el objeto sobre gris
  neutro y devuelve image + mask + engine. Impura, nunca lanza. Adaptada de
  backend/bg_removal.py con firma de ruta (image_path) y salida dict, demo CLI
  JSON-serializable.
- depth_to_relief_glb_py_datascience (v1.1.0): añade el parámetro opcional mask
  para recortar la malla de relieve al objeto (descarta las caras del fondo),
  cerrando la cadena con remove_background. Aditivo (mask=None = comportamiento
  previo), fiel al original de backend/depth.py.
- docs/capabilities/img-to-3d.md: incorpora remove_background como paso 0
  (pre-proceso), actualiza el flujo a 3 pasos encadenados, la tabla de funciones
  (4), el ejemplo end-to-end con mask y las deps (rembg/opencv).
- docs/capabilities/INDEX.md: conteo del grupo 3 -> 4.

Las dos funciones ya presentes (estimate_image_depth, depth_to_relief_glb) y el
pipeline build_relief_glb_from_image fueron promovidas en una ronda previa.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 21:43:08 +02:00

6.0 KiB

group, description
group description
img-to-3d Convertir una imagen 2D en un modelo 3D: estimacion de profundidad monocular (Depth-Anything-V2) + reconstruccion de una malla de relieve texturizada exportada a glTF binario (.glb).

img-to-3d — Capability Group

Cluster de funciones Python (dominio datascience) para el flujo imagen 2D → modelo 3D. A partir de una sola foto se estima un mapa de profundidad monocular con un modelo de vision y se reconstruye una malla de relieve (heightmap) texturizada con la imagen original, exportada como .glb cargable por cualquier visor glTF (three.js useGLTF/GLTFLoader, Babylon, model-viewer).

Promovido desde la app img_to_3d_webapp (su backend incrustaba estas funciones; ver backend/depth.py y backend/bg_removal.py). El flujo canonico encadena un pre-proceso opcional de fondo con los dos pasos de reconstruccion:

[remove_background (imagen -> rgb+mask)] -> estimate_image_depth (imagen -> depth+image) -> depth_to_relief_glb (depth+image[+mask] -> .glb)

Funciones

ID Firma corta Que hace
remove_background_py_datascience remove_background(image_path, engine?) -> dict Pre-proceso (paso 0). Elimina el fondo en cascada rembg -> GrabCut -> umbral y compone el objeto sobre gris neutro. Devuelve image PIL + mask ndarray. La mask se pasa a depth_to_relief_glb para recortar la malla al objeto.
estimate_image_depth_py_datascience estimate_image_depth(image_path, model_name?, device?, use_cache?) -> dict Estima profundidad monocular con Depth-Anything-V2 (GPU/CPU). Devuelve depth ndarray [0,1] + image PIL. Paso 1.
depth_to_relief_glb_py_datascience depth_to_relief_glb(image, depth, out_glb_path, z_scale?, max_dim?, mask?) -> dict Convierte depth+image en una malla de relieve texturizada y la exporta a .glb. Con mask opcional recorta las caras del fondo. Paso 2.
build_relief_glb_from_image_py_pipelines build_relief_glb_from_image(image_path, out_glb_path, model_name?, device?, z_scale?, max_dim?) -> dict Pipeline one-shot: compone estimacion + relieve en una sola llamada (imagen -> .glb). Salida JSON-serializable, apta para fn run.

Las cuatro son impuras (cargan modelo / GPU / escriben archivo), devuelven dict con status (ok/error) y nunca lanzan: los fallos vuelven como {status:'error', error:str}. El pipeline ademas marca stage (estimate/relief) en el error. remove_background en engine="auto" nunca falla (cae al umbral NumPy puro sin deps externas).

Ejemplo canonico (end-to-end imagen → glb)

# Requiere un venv con torch + transformers + trimesh + pillow + numpy.
# Import PLANO: el paquete datascience.__init__ arrastra deps de otros dominios (bs4, duckdb...)
# ausentes en el venv de vision. Ver "Fronteras / gotchas".
import sys
sys.path.insert(0, "python/functions/datascience")
from remove_background import remove_background
from estimate_image_depth import estimate_image_depth
from depth_to_relief_glb import depth_to_relief_glb

IMG = "apps/img_to_3d_webapp/samples/cats.jpg"
OUT = "/tmp/cats_relief.glb"

# Paso 0 (opcional pero recomendado): aislar el objeto del fondo. La mask recorta la malla.
cut = remove_background(IMG)                   # engine='auto' -> rembg -> grabcut -> umbral
assert cut["status"] == "ok"
print(cut["engine"], cut["fg_fraction"])       # p.ej. rembg:u2net 0.42

est = estimate_image_depth(IMG)               # device='auto' -> GPU si hay
assert est["status"] == "ok"
# est["depth"]: ndarray HxW float32 [0,1] (1=mas cerca)  |  est["image"]: PIL.Image RGB

# Pasando la mask del paso 0, las caras del fondo se descartan: malla solo del objeto.
res = depth_to_relief_glb(est["image"], est["depth"], OUT, z_scale=0.35, max_dim=220, mask=cut["mask"])
assert res["status"] == "ok"
print(res["glb_path"], res["vertices"], res["faces"])   # /tmp/cats_relief.glb 36300 71832
# OUT es un glTF binario valido: trimesh.load(OUT) devuelve una Scene texturizada.

O en una sola llamada con el pipeline (recomendado para fn run / Launcher TUI):

./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, ...}

Fronteras

  • Es relieve 2.5D, no reconstruccion volumetrica. Deforma un plano segun la profundidad (heightmap); no recupera caras ocultas ni el volumen trasero del objeto. Para 3D real multivista/fotogrametria, NSP/Gaussian Splatting, esto NO aplica.
  • Profundidad relativa, no metrica. Depth-Anything devuelve disparidad normalizada a [0,1]; no comparable entre imagenes ni en unidades del mundo real.
  • No cubre el render/visualizacion. Producir el .glb es el limite del grupo. Cargarlo y subirlo a GPU (OpenGL) en una app C++/ImGui es el grupo mesh-3d (gltf_load_mesh_cpp_gfx carga justamente este tipo de .glb). img-to-3d produce; mesh-3d consume/renderiza.
  • Deps pesadas y de dos mundos. Requiere torch+transformers (vision), trimesh (mesh) y, para remove_background, rembg+onnxruntime (segmentacion) y opencv-python (GrabCut) — todas opcionales: el umbral de remove_background es NumPy puro. Hoy viven en el venv de img_to_3d_webapp, NO en el venv del registry. Ademas el datascience.__init__ arrastra deps de scrapers (bs4...) que no estan en el venv de vision, por eso el import es plano (al modulo) y no via el paquete. fn run de estas funciones exige un venv que combine ambos mundos (torch + transformers + trimesh + rembg/opencv + las deps del dominio datascience). Ver gotchas en cada .md.

Prerequisitos

  • GPU NVIDIA + CUDA recomendada (corre en CPU pero lento). Primera ejecucion descarga los pesos del modelo de profundidad a ~/.cache/huggingface/ y el de rembg (U2Net ~170 MB) a su cache.
  • Paquetes: torch, transformers, trimesh, pillow, numpy. Para el recorte de fondo de mayor calidad: rembg (+onnxruntime) y opencv-python (ambos opcionales; sin ellos remove_background cae al umbral NumPy).