---
name: comfyui_generate_views_from_image
kind: function
lang: py
domain: ml
version: "1.1.0"
purity: impure
signature: "def comfyui_generate_views_from_image(image_name: str, *, method: str = \"auto\", server: str = \"127.0.0.1:8188\", azimuths: tuple = (90, 180, 270), elevation: float = 0.0, video_frames: int = 21, sv3d_width: int = 576, sv3d_height: int = 576, dest_dir: str | None = None, validate_only: bool = False, wait_timeout: float = 300.0, timeout: float = 30.0) -> dict"
description: "Genera vistas novel-view desde 1 imagen para alimentar el 3D multi-vista de ComfyUI. Usa los sintetizadores NATIVOS StableZero123 (StableZero123_Conditioning_Batched, control de azimuth; devuelve back/left/right) o SV3D (SV3D_Conditioning, orbita de N frames equiespaciados en 360 grados; devuelve el orbit completo + cardinales mapeados). Ambos caminos operativos y probados en 8 GB lowvram. HONESTA: consulta /object_info, comprueba que el nodo Y su checkpoint estan instalados, y SOLO encola si hay camino viable; si no, devuelve {ok: False, reason} con la accion para habilitarlo SIN tocar la GPU. Compone object_info + validate + submit + wait + fetch_output_image. Impura: HTTP + disco."
tags: [comfyui, ml, img-to-3d, novel-view, multiview, stablezero123, sv3d]
uses_functions: [comfyui_object_info_py_ml, comfyui_validate_workflow_py_ml, comfyui_submit_workflow_py_ml, comfyui_wait_result_py_ml, comfyui_fetch_output_image_py_ml]
uses_types: []
returns: []
returns_optional: false
error_type: error_go_core
imports: []
params:
  - name: image_name
    desc: "Nombre del archivo de imagen (vista frontal) en el input/ del servidor ComfyUI. Debe existir ya (subelo con POST /upload/image)."
  - name: method
    desc: "'zero123' (StableZero123, control directo de azimuth), 'sv3d' (orbita SVD, mejor consistencia) o 'auto' (elige el primero cuyo nodo+checkpoint esten instalados, prefiriendo zero123). keyword-only."
  - name: server
    desc: "host:port de ComfyUI. keyword-only."
  - name: azimuths
    desc: "Angulos (grados) de las vistas a generar; 90=right, 180=back, 270=left (0=front la aporta el caller). Se asumen equiespaciados para el batch. keyword-only."
  - name: elevation
    desc: "Elevacion de camara en grados para todas las vistas. keyword-only."
  - name: video_frames
    desc: "SOLO sv3d. Numero de frames del orbit (vistas equiespaciadas en 360 grados que el modelo sintetiza en una pasada). Default 21 (el nativo de SV3D). Bajalo (7-12) para reducir VRAM en 8 GB lowvram a costa de menos densidad angular. keyword-only."
  - name: sv3d_width
    desc: "SOLO sv3d. Ancho en px de cada frame del orbit. Default 576 (nativo). Bajalo para reducir VRAM. keyword-only."
  - name: sv3d_height
    desc: "SOLO sv3d. Alto en px de cada frame del orbit. Default 576 (nativo). keyword-only."
  - name: dest_dir
    desc: "Carpeta local donde descargar las vistas generadas. Si None, no se descargan (solo se devuelven los nombres del output del servidor). keyword-only."
  - name: validate_only
    desc: "Si True, construye el workflow y lo valida contra /object_info SIN encolar ni tocar la GPU; devuelve el veredicto estructural (valid, missing_nodes, missing_models). Util para comprobar viabilidad antes de comprometer GPU. keyword-only."
  - name: wait_timeout
    desc: "Timeout de espera de la generacion en segundos. keyword-only."
  - name: timeout
    desc: "Timeout HTTP por request en segundos. keyword-only."
output: "dict. Viable zero123: {ok: True, method, views: {back, left, right -> ruta/nombre}, prompt_id, available, reason: '', error: ''}. Viable sv3d: ademas trae el orbit completo: {..., views: {cardinales mapeados al frame mas cercano}, frames: [ruta/nombre de cada uno de los N frames del orbit], frame_count: N}. validate_only=True (no encola): {ok: <valido>, method, validated: True, valid, missing_nodes, missing_models, available, ...}. Sin nodo+modelo viable (stub honesto, NO encola): {ok: False, method, views: {}, reason: '<que falta y como instalarlo>', available: {nodes, ckpts, ckpt_combo}, error: ''}. Fallos de red/encolado: ok=False con error."
tested: false
tests: []
test_file_path: ""
file_path: "python/functions/ml/comfyui_generate_views_from_image.py"
---

## Ejemplo

```python
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_generate_views_from_image import comfyui_generate_views_from_image

# Comprobar viabilidad SIN encolar (no toca GPU) — recomendado antes de generar
chk = comfyui_generate_views_from_image("front.png", validate_only=True)
# chk == {"ok": True, "method": "zero123", "validated": True, "valid": True,
#         "missing_nodes": [], "missing_models": [], ...}  (si el ckpt esta instalado)

# 'front.png' debe estar ya en el input/ del servidor (POST /upload/image)
res = comfyui_generate_views_from_image("front.png", method="auto", dest_dir="/tmp/views")

if res["ok"]:
    # res["views"] == {"right": "/tmp/views/novel_view_00001_.png",
    #                  "back":  "/tmp/views/novel_view_00002_.png",
    #                  "left":  "/tmp/views/novel_view_00003_.png"}
    # -> alimentan comfyui_build_image_to_3d_multiview_workflow junto a la frontal
    ...
else:
    # Stub honesto: el checkpoint del sintetizador no esta instalado.
    print(res["reason"])         # que falta + comando para instalarlo
    print(res["available"])      # {nodes: {...}, ckpts: {...}}
```

### Camino SV3D (orbit de N frames)

```python
# SV3D: 1 imagen -> orbit de 21 vistas equiespaciadas en 360 grados, en una pasada.
# La imagen debe estar ya en input/ del servidor. Cabe en 8 GB lowvram (~75 s, peak ~5.7 GB).
res = comfyui_generate_views_from_image(
    "sv3d_test_robot.png", method="sv3d",
    video_frames=21, sv3d_width=576, sv3d_height=576,   # nativo; baja para menos VRAM
    dest_dir="/tmp/sv3d_views", wait_timeout=900.0)

if res["ok"]:
    res["frame_count"]   # 21 — orbit completo
    res["frames"]        # [".../sv3d_view_00001_.png", ... x21]  (orbit entero)
    res["views"]         # {"right": frame06, "back": frame11, "left": frame17}
    #                      cardinales mapeados al frame mas cercano del orbit,
    #                      para alimentar comfyui_build_image_to_3d_multiview_workflow
```

Lánzalo con el python del venv (import de arriba o heredoc). `./fn run` directo no aplica: la firma usa `*` (keyword-only). El bloque `__main__` ejecuta el caso sin modelos instalados y muestra el `ok=False` honesto.

## Cuando usarla

Cuando tengas UNA sola imagen de un objeto y quieras reconstruir un 3D multi-vista
mejor (cara trasera y laterales definidos, no alucinados). Genera con esta función las
vistas back/left/right que faltan y pásalas, junto a la frontal, a
`comfyui_build_image_to_3d_multiview_workflow` (Hunyuan3D-2mv). Si tienes fotos reales
del objeto desde varios ángulos, NO la necesitas: úsalas directamente (mejor resultado;
report 0073). Esta función es el camino sintético cuando solo hay 1 vista.

## Gotchas

- **No finge resultados**: si el nodo o su checkpoint no están instalados, devuelve
  `{ok: False, reason: ...}` con el comando para habilitarlo y **NO encola nada** (no
  compite por la GPU). Estado en este equipo (24/06/2026, verificado contra `/object_info`):
  `3D_stable_zero123.ckpt` **SÍ** (zero123 viable) y `3D_sv3d_p.safetensors` **SÍ** (sv3d viable
  y probado en GPU, ver Capability growth log). Para sv3d acepta `3D_sv3d_p.safetensors`
  (preferido, orbita con elevación variable) o `sv3d_u.safetensors` (orbita uniforme).
- **`image_name` debe existir en `input/` ANTES de generar**: la función no sube la imagen
  (no la inventa). Si pasas un `image_name` que no está en el `input/` del servidor, el
  POST /prompt devuelve HTTP 400 (`prompt_outputs_failed_validation` de LoadImage) y la
  función lo propaga como `ok=False` con el body — comportamiento correcto, no un bug.
  Usa `validate_only=True` para comprobar el grafo sin necesidad de la imagen ni de GPU.
- **SV3D y la VRAM (8 GB lowvram)**: el orbit nativo de 21 frames @576×576 **cabe** en
  8 GB lowvram (medido: ~75 s, peak ~5.7 GB de 8 GB con el escritorio usando ~2.9 GB). El
  checkpoint `3D_sv3d_p.safetensors` pesa ~9.4 GB en disco (incluye el backbone SVD completo +
  CLIP-vision + VAE), NO ~2 GB; ComfyUI lo carga por capas en lowvram. Si diera OOM en un
  equipo más justo, baja `video_frames` (p. ej. 12) y/o `sv3d_width`/`sv3d_height` (p. ej.
  320); reducir frames degrada la densidad del orbit (el modelo se entrenó para 21).
- **SV3D orbit vs zero123 azimuths**: SV3D produce N frames equiespaciados en 360° empezando
  por la vista frontal (frame 0 = az 0); el azimuth por-frame **no es controlable**
  individualmente como en zero123. Para encajar con el consumidor multi-vista, los `azimuths`
  pedidos se mapean al frame del orbit más cercano (con 21 frames: right≈frame 6, back≈frame
  11, left≈frame 17) en `views`, y el orbit completo va en `frames`.
- **Encola trabajo de GPU** sólo en el camino viable: `comfyui_submit_workflow` dispara
  generación real. Respeta el aislamiento del server (coordina si otro agente lo usa).
- **Vistas sintéticas ≠ fotos reales**: no son perfectamente ortogonales ni 100%
  consistentes; introducen ruido que el modelo mv puede amplificar. Para máxima fidelidad,
  fotos reales > síntesis. MV-Adapter (mejor sintetizador) es custom node, fuera de alcance.
- `azimuths` se asume equiespaciado (el batch usa un incremento fijo). Mapeo de ángulo a
  nombre: 0=front, 90=right, 180=back, 270=left.

## Capability growth log

- v1.1.0 (24/06/2026) — implementado el camino `sv3d` (antes `NotImplementedError`):
  builder `SV3D_Conditioning` + `VideoLinearCFGGuidance` + `KSampler` + `VAEDecode` que
  produce el orbit de N frames; nuevos params `video_frames`/`sv3d_width`/`sv3d_height`
  configurables; salida extendida con `frames`/`frame_count`; soporta `3D_sv3d_p`/`sv3d_u`.
  Probado en GPU (8 GB lowvram): 21 frames 576×576 en ~75 s, peak ~5.7 GB
  (prompt_id `0caeedf4-…`). Modelo `3D_sv3d_p.safetensors` descargado a `checkpoints/`.
