Files
fn_registry/python/functions/datascience/remove_background.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

5.8 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path, source_file
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports params output tested tests test_file_path file_path source_file
remove_background function py datascience 1.0.0 impure def remove_background(image_path: str, engine: str = 'auto') -> dict Elimina el fondo de una imagen con cascada de motores (rembg/U2Net -> OpenCV GrabCut -> umbral NumPy), compone el objeto sobre fondo gris neutro y devuelve image+mask+engine. Paso de pre-proceso del flujo img->3D (grupo img-to-3d): su mask alimenta depth_to_relief_glb para recortar la malla de relieve al objeto.
img-to-3d
datascience
background-removal
segmentation
rembg
grabcut
opencv
computer-vision
mask
false error_go_core
name desc
image_path Ruta a la imagen de entrada. Cualquier formato que PIL.Image.open abra (jpg, png, webp, RGBA...). Si no existe o no es imagen valida, se devuelve status error. Un PNG RGBA ya recortado se reaprovecha en modo auto (passthrough:alpha).
name desc
engine Motor de segmentacion. 'auto' (default) prueba en cascada rembg:u2net -> opencv:grabcut -> threshold:border y NUNCA falla (cae al umbral NumPy puro sin deps externas). Forzar uno: 'rembg' (red neuronal U2Net, mejor calidad, deps pesadas), 'grabcut' (OpenCV, rectangulo central), 'threshold' (distancia al color medio de los bordes, NumPy puro, objeto centrado). Si se fuerza un motor y no esta disponible/falla o produce mascara degenerada -> status error.
dict. Exito: {status:'ok', image: PIL.Image RGB del objeto compuesto sobre fondo gris neutro (127,127,127), mask: ndarray HxW uint8 (0..255, 255=objeto), engine: str del motor usado ('rembg:u2net' | 'opencv:grabcut' | 'threshold:border' | 'passthrough:alpha'), height:int, width:int, fg_fraction: float (fraccion de pixeles objeto, redondeada a 4 decimales)}. Error: {status:'error', error:str} (ruta invalida, motor desconocido, motor forzado no disponible/fallido, o ningun motor produjo una mascara valida). No lanza nunca. El demo CLI (__main__) imprime un resumen JSON sin el ndarray ni la imagen y, si se pasa out_dir, guarda rgb.png + mask.png. false
python/functions/datascience/remove_background.py apps/img_to_3d_webapp/backend/bg_removal.py

Ejemplo

# Requiere un venv con pillow + numpy (rembg/opencv solo si fuerzas esos motores; el umbral es NumPy puro).
# Import PLANO al modulo: el paquete datascience.__init__ arrastra deps de otros dominios
# (bs4, duckdb...) que no estan en ese venv. Ver Gotchas.
import sys
sys.path.insert(0, "python/functions/datascience")
from remove_background import remove_background

res = remove_background("apps/img_to_3d_webapp/samples/cats.jpg", engine="auto")
assert res["status"] == "ok"
print(res["engine"])                 # p.ej. "rembg:u2net" (o "opencv:grabcut" / "threshold:border")
print(res["height"], res["width"])   # p.ej. 1024 768
print(res["mask"].shape, res["mask"].dtype)   # (1024, 768) uint8 (255=objeto)
assert 0.0 < res["fg_fraction"] < 1.0
# res["mask"] (ndarray HxW uint8) alimenta depth_to_relief_glb para recortar la malla al objeto.
# res["image"] es el objeto compuesto sobre gris neutro, listo para estimar profundidad.

Lanzable como demo (imprime resumen JSON, sin serializar el ndarray; guarda PNGs si das out_dir):

./fn run remove_background_py_datascience apps/img_to_3d_webapp/samples/cats.jpg auto /tmp/cut
# {"status": "ok", "engine": "rembg:u2net", "height": 1024, "width": 768,
#  "fg_fraction": 0.4123, "rgb_path": "/tmp/cut/rgb.png", "mask_path": "/tmp/cut/mask.png"}

Cuando usarla

Como pre-proceso ANTES de estimar profundidad en el flujo img->3D: aislar el objeto evita que el modelo de profundidad estire el fondo plano, y la mask permite recortar la malla de relieve al objeto (se pasa a depth_to_relief_glb). Tambien para segmentacion de primer plano generica cuando necesitas separar un objeto de su fondo y componerlo sobre un color neutro (recortes para catalogos, datasets, miniaturas).

Gotchas

  • Impura: segun el motor carga modelos neuronales y lee disco. rembg/onnxruntime (~170MB) DESCARGA el modelo U2Net la primera vez a su cache (~/.u2net/), requiere red en esa primera carga; opencv-python para GrabCut; el umbral (threshold:border) es NumPy puro sin deps externas.
  • Estado de proceso: _REMBG_SESSION cachea la sesion rembg a nivel de modulo para no recargar los pesos en cada llamada. Es estado mutable compartido del proceso y ocupa RAM hasta que el interprete muere.
  • engine='auto' nunca lanza: prueba rembg -> grabcut -> threshold y siempre cae al umbral NumPy puro si los anteriores no estan disponibles o fallan. Forzar un motor concreto SI puede devolver status error (motor no instalado, fallo, o mascara degenerada).
  • Mascara degenerada: si la fraccion de objeto resulta < 0.01 o > 0.995 la mascara se descarta (casi todo fondo o casi todo objeto) y en modo auto se prueba el siguiente motor.
  • threshold:border es de baja calidad: asume objeto centrado con los bordes de la imagen siendo fondo (calcula la distancia al color medio de los bordes). Es el fallback de ultimo recurso.
  • passthrough:alpha: si la imagen ya viene recortada (PNG RGBA con alfa por debajo de 128) se reutiliza su canal alfa como mascara, SOLO en modo auto. Si fuerzas un motor concreto se respeta esa eleccion e ignora el alfa existente.
  • Import plano: importa el modulo directo (sys.path a python/functions/datascience + from remove_background import remove_background), NO from datascience import .... El datascience.__init__ carga todo el dominio (scrapers con bs4, duckdb...) con deps ajenas a esta funcion que romperian el import del paquete en el venv de vision.
  • Nunca lanza: errores (ruta invalida, motor forzado no disponible, OOM) vuelven como {status:'error', error:str}.