← Trabajos

Un preset fotográfico como workflow de ComfyUI, con la medición a la vista

Prueba propia de portfolio, no un trabajo de cliente. 7 fotos reales con licencia CC0 (Wikimedia Commons). El preset mejora fotos existentes: no genera caras, manos ni objetos. Estimaciones marcadas como tales.

Gráfico de barras de la estructura conservada (correlación local de luminancia) por región, preset frente a clásico sin IA: sujeto 0,98 frente a 0,96, borde 0,97 frente a 0,98, cielo 0,91 frente a 0,99, resto 0,98 frente a 0,99
Estructura conservada respecto al original, por región, en 7 fotos reales. Más alto es mejor; el preset pierde estructura en el cielo.
Ver el repositorio en GitHub →github.com/grawwww-studio/comfyui-photo-preset · código MIT · workflows, nodos, cliente y resultados

El problema

Una app de edición de fotos que ya funciona en producción tiene el pipeline en Python: preprocesar y escalar, mejorar con IA (por ejemplo corregir una foto sobreexpuesta), gradación con LUTs y escalado final. Quiere pasarlo a ComfyUI ejecutado por API, con cada preset de un fotógrafo como un workflow y el backend orquestando. Y con una regla estricta: es mejora de fotos reales, no generación; se tienen que conservar la identidad, la textura de la piel y los detalles de la escena, sin caras, manos ni objetos inventados.

Qué hicimos

  • Un preset = un JSON de workflow, lanzado por un cliente Python sobre la API de ComfyUI (/prompt, websocket, /history): registra segundos por nodo y etapa, pico de VRAM y coste por foto. Versiones fijadas (ComfyUI 0.37.0, hashes de modelos).
  • Nodos propios en Python: refinado de recorte con filtro guiado, recuperación de exposición por regiones (separa base y detalle y deja el detalle intacto), nodo de LUT .cube con máscaras por región (el «porta tu gradación a nodos») y escalado x2 con anclaje de bajas frecuencias.
  • Modelos con licencia comprobada: BiRefNet (MIT) para el recorte y 2xNomosUni SPAN (CC BY 4.0) para el escalado. Descartamos lo que no pudimos verificar (por ejemplo, los pesos de RealESRGAN no declaran licencia propia).
  • Una versión clásica sin IA (auto-niveles + la misma LUT + Lanczos) para compararla foto a foto, y una evaluación sobre un set fijo con hojas lado a lado, métricas de fidelidad y mapas de «dónde cambió la estructura».

Ejemplos: original, clásico sin IA, preset

Tres de las 7 fotos, las que no tienen personas. Las hojas completas, los recortes a 2x y los mapas de cambio están en el repositorio. Qué se ve es lectura nuestra: el preset es más conservador y más plano que el clásico, que suele ser más «punchy».

Ópera de Sídney a mediodía: original
original
Ópera de Sídney a mediodía: clásico, sin IA
clásico, sin IA
Ópera de Sídney a mediodía: preset
preset

Exterior de mediodía, con blancos fuertes y cielo azul. Foto: Bernard Spragg, CC0.

Mirador con cielo azul y montañas: original
original
Mirador con cielo azul y montañas: clásico, sin IA
clásico, sin IA
Mirador con cielo azul y montañas: preset
preset

Cielo azul con zonas quemadas y un objeto en primer plano. El preset baja el cielo y aplana su textura: es el peor dato de estructura de la serie (ver abajo). Foto: Markus Spiske, CC0.

Interior de una cafetería: original
original
Interior de una cafetería: clásico, sin IA
clásico, sin IA
Interior de una cafetería: preset
preset

Interior con luz mixta, sin personas. Foto: Andy Li, CC0.

Números

ConceptoValor
GPUNVIDIA RTX 4090 (24 GB), compartida con otros contenedores en reposo
Foto de entrada → salida1280 px lado largo → 2560 px
Tiempo por foto, en caliente (mediana)5,94 s (4,9–7,5 s)
Misma foto, versión clásica sin IA0,85 s
VRAM sobre la base (pico de la tarjeta)2,9 GB
Coste por foto, ESTIMACIÓN0,0015 $ = segundos × 0,89 $/h, precio listado de RunPod para RTX 4090 en https://www.runpod.io/pricing el 2026-10-16. Supone GPU ocupada al 100 %, sin arranques en frío ni almacenamiento; no se ha usado hardware alquilado.

La mitad del tiempo del preset son dos etapas sin optimizar (recuperación de exposición 2,5 s y segmentación 1,9 s). El «primer run tras liberar modelos» (5,0 s) no es un arranque en frío real: los archivos estaban en caché del sistema.

Fidelidad: ¿se conserva la estructura?

RegiónPresetClásicoPeor foto del preset
Sujeto0,9840,9610,953
Banda de borde (pelo)0,9700,9810,943
Cielo (solo 3 fotos)0,9090,9940,800
Resto0,9800,9860,945

Correlación cruzada normalizada local de la luminancia contra el original, solo en píxeles con textura (1,0 = misma estructura; una edición de exposición o color no la cambia, una estructura inventada o destruida sí). En el sujeto el preset conserva mejor la estructura que el clásico; en el cielo es peor: el hombro de altas luces aplana la textura de cielos claros.

  • Color: el preset mueve el color del sujeto menos que el clásico (ΔE medio 8,0 frente a 14,1) y casi no cambia el tono (2,9° frente a 9,5°). Son medidas de cuánto se movió, no de error: no hay una imagen «correcta».
  • Escalado x2: al reducir de nuevo el resultado 2x, coincide con la imagen de partida a 39,4 dB de PSNR (Lanczos solo: 41,1 dB; el modelo SPAN sin anclaje: 32,5 dB y oscurecía la imagen). Aun así añade ×1,34 más energía de detalle: es la nitidez, y también lo que no podemos certificar como «no inventado».
  • Nodo de LUT: frente a una implementación numpy independiente que lee el mismo .cube, la diferencia máxima es 1/255 y el 98,5 % de los píxeles es idéntico.
  • Determinismo: dos ejecuciones repetidas dan imágenes idénticas (98 pares de PNG comparados, diferencia máxima 0).

7 fotos, 3 repeticiones, una GPU, un preset ajustado a mano sobre este tipo de fotos: es una prueba de método, no un benchmark.

Qué sigue fallando y qué no hicimos

  • El cielo se detecta con una heurística, no con un modelo. De las 4 fotos con cielo lo encuentra bien en 2, se niega en 2 (nieve blanca, bruma beige) y da un falso positivo en una calle (edificios en sombra).
  • Lo quemado no se recupera: en la foto más sobreexpuesta de la serie (11,5 % de píxeles quemados) queda gris plano, porque el detalle nunca estuvo en el archivo. Un modelo generativo «inventaría» ahí, justo lo que este trabajo no permite; no probamos ninguno.
  • Contraluz fuerte: la subida de sombras está limitada para no amplificar ruido, así que un sujeto muy oscuro sigue oscuro.
  • El refinado del recorte es mixto: alinea mejor los bordes por nuestro indicador (0,60 frente a 0,51, sin recorte de referencia: no es una medida de precisión), pero mete rayas en una foto con fondo muy claro. Además BiRefNet devuelve «el objeto saliente», no «la persona».
  • No hicimos: segmentación de piel, relight generativo, LoRA de estilo de un fotógrafo ni despliegue en la nube (el Dockerfile no se ha construido y nada corrió en RunPod ni Modal). Tampoco medimos arranque en frío, concurrencia ni otras tarjetas.

Qué recibe un cliente

Lo mismo que ves aquí, aplicado a tu pipeline: tus presets convertidos en workflows de ComfyUI con una API estable para tu backend, nodos a medida para la lógica que hoy vive en tu Python (gradación, máscaras, recuperación de exposición), versiones y modelos fijados con su licencia comprobada, una evaluación con tu set de fotos y una lista honesta de lo que falla.

Herramientas a medida (extensiones, nodos, plugins y conectores): desde 600 €, sin IVA. Es un precio de partida: tras la primera conversación, la propuesta cierra el alcance y el precio. Detalle en Equipos técnicos, o escríbenos a hello@grawwww.xyz. Respondemos en menos de 48 horas.

Créditos y licencias

  • BiRefNet (recorte), licencia MIT.
  • Escalado: 2xNomosUni_span_multijpg de Philip Hofmann, CC BY 4.0 (https://huggingface.co/Phips/2xNomosUni_span_multijpg). La licencia del conjunto de entrenamiento no se ha verificado.
  • ComfyUI (GPL-3.0): lo usamos tal cual, sin modificarlo ni distribuirlo; nuestro paquete de nodos es un plug-in aparte, con licencia MIT.
  • Fotos de prueba: CC0, de Wikimedia Commons (autores y archivos en el repositorio). Una foto se retiró antes de publicar porque mostraba a una persona identificable sin autorización de imagen.
  • Nuestro código, README y resultados: licencia MIT. No se redistribuyen pesos de modelos.
Código, resultados y licencias en GitHub →github.com/grawwww-studio/comfyui-photo-preset