Saltar al contenido
Fantástico Mundo de Jon
RSS

Dibujos para colorear con IA local: desde el prompt hasta el archivo que imprime bien

Generar la imagen es la parte fácil, y es donde todos los tutoriales terminan. Lo que decide si el niño puede pintar es lo que sigue: binarizar, vectorizar e imprimir sin serrado.

¿Con prisa? Pide el TL;DR a Claude — lee la página y la resume.

es Traducción automática por qwen3:32b, revisada por el autor. Leer el original en portugués

Mi hija pidió un dibujo de dinosaurio para pintar. Fui a buscar en internet y encontré el habitual: un PNG de seiscientos píxeles con marca de agua en el centro, tres anuncios alrededor, y una línea que se convierte en escalones en cuanto sale de la impresora.

Tengo seis máquinas aquí corriendo un modelo local. Pensé que lo resolvería en diez minutos.

Le llevó una tarde, y el problema no estaba donde yo imaginaba. La imagen sale fácil. Lo que da trabajo es hacer que llegue al papel de una manera que una niña de cinco años pueda pintar.

¿Qué modelo y por qué no el más famoso

black-forest-labs/FLUX.2-klein-4B

Parámetros
4 B
Licencia
Apache 2.0
Transformer
7,75 GB (BF16)
Codificador de texto
8,04 GB (BF16)
VAE
0,17 GB
Total en disco
15,96 GB

Casi todos los tutoriales usan el FLUX.1 dev, que es el más conocido. Yo también empecé por él, hasta que me detuve a leer la licencia: es no comercial.

Para el dibujo de mi hija, da igual. Pero la profesora de ella lo vio y pidió copias para toda la clase, y la conversación cambia. No soy abogado y no voy a fingir que sé exactamente dónde está la línea entre uso personal y distribución, pero me pareció más sencillo usar un modelo en el que esa pregunta no exista.

El klein de 4B es Apache 2.0. Lo que sale de él es tuyo, sin asterisco.

¿Cuánto de VRAM

Precisión Transformer Texto VAE Total
BF16 (como publicado) 7,75 8,04 0,17 15,96
FP8 3,88 4,02 0,17 8,06
Q4 (~31%) 2,40 2,49 0,17 5,06
GB decimales, calculados a partir del tamaño real de los archivos en el repositorio oficial de Hugging Face. Es aritmética de disco, no medición de VRAM ocupada: el runtime aún añade buffers encima.

Hay un detalle que cambia bastante la cuenta en una placa pequeña. El codificador de texto solo trabaja mientras se lee el prompt. Después de eso puede salir de la memoria, y el transformer termina el servicio solo.

Estrategia Pico en BF16 Pico en FP8
Tudo carregado junto 15,96 8,06
Codificador descarregado após o prompt 8,04 4,04
Pico teórico en GB. Con descargue secuencial el pico se convierte en el componente aislado más grande, y no en la suma de los tres. El precio son unos segundos más cuando cambias de prompt.

En FP8 con descargue el pico teórico baja a 4 GB. Eso cambia quién puede jugar con esto: cabe hasta en una placa de 8 GB.

¿Cabe en mis placas?

Máquina Memória (GB) BF16 completo FP8 FP8 + descarregamento
RTX 5070 · 12 GiB 12,9 no cabe sobra
RTX 5070 Ti · 16 GiB 17,2 ajustado sobra sobra
RTX 4090 · 24 GiB 25,8 cabe sobra sobra
RTX 5090 · 32 GiB 34,4 sobra sobra sobra
MacBook Pro M4 Max · 48 GiB 51,5 cabe sobra sobra
Mini PC · 96 GiB unificados 103,1 sobra sobra sobra
Comparación de la aritmética anterior con la memoria de cada máquina, más 1 GB de margen para el runtime. 'Ajustado' quiere decir que carga pero sin margen para una resolución mayor. Ninguno de estos es tiempo medido, solo lo que cabe.

La 5070 de 12 GB es el caso interesante. En los posts sobre LLM vive quedando fuera: no carga un 27B, no carga un 32B, siempre mira a los demás. Aquí corre todo con margen en FP8. Generación de imagen es mucho más amigable con una placa modesta que texto, y nadie comenta eso.

En el Mac, con MLX

El camino en el Mac no es el mismo. CUDA no existe allí, y usar PyTorch con backend MPS funciona pero es el peor de los mundos.

Lo que se usa es el mflux, una reimplantación de Flux en MLX, el framework de Apple. Ya soporta la familia klein, tiene cuantización de 4 y 8 bits integrada y una flag --low-ram para máquina apretada.

uv tool install mflux

mflux-generate \
  --model klein \
  --quantize 8 \
  --steps 4 \
  --height 1440 --width 1024 \
  --prompt "coloring book page, thick black outlines, white background, a friendly dinosaur wearing rain boots" \
  --output dino.png

Funciona bien. Solo es más lento, y vale entender por qué.

¿Por qué el Mac tarda más

Esto me molestó un tiempo, porque en los tests con LLM el Mac suele salir bien. Un M4 Max sigue una buena placa generando texto. Luego le mandas que genere imagen y la diferencia es gritante.

No es contradicción. Los dos problemas se atascan en lugares diferentes.

Generar texto, en la parte de decodificación, es básicamente leer los pesos enteros de la memoria cada token generado. La cuenta en sí es pequeña; el cuello de botella es el transporte. Quien manda es ancho de banda, y es exactamente allí donde la memoria unificada compite a igualdad de condiciones.

Generar imagen es otro problema. El modelo pasa veinte, treinta veces por el mismo latente, y cada pasada es multiplicación de matriz grande. Los pesos ya están cargados y se quedan quietos; lo que corre sin parar es cálculo. Allí quien manda es FLOPS.

Máquina TFLOPS Onde isso pesa
RTX 4090 82,6 geração de imagem
Apple M4 Max 18,4 geração de imagem
Números de especificación de fábrica, no medición mía. Cuatro veces y media de diferencia en cálculo bruto, y es eso lo que aparece en el cronómetro cuando el cuello de botella es compute en vez de banda.

Cuatro veces y media de diferencia en cálculo bruto. Suma a eso el hecho de que el kernel de difusión viene siendo optimizado para CUDA desde hace años y para MLX desde mucho menos tiempo, y el resultado es lo que se ve.

Orden de magnitud para calibrar expectativas: relatos públicos ponen el klein 4B en 30 a 40 segundos por imagen de 1024px en un M1 Max. No medí en mi M4 Max aún, y no voy a fingir que medí.

La conclusión práctica es chata pero útil: si tienes placa NVIDIA y un Mac, genera en el PC y edita en el Mac. Y si solo tienes Mac, el klein de 4B es la elección correcta justamente por ser pequeño.

El prompt

Página de colorir no es dibujo bonito. Es un dibujo con un montón de restricciones:

coloring book page for young children, black and white line art,
thick clean bold outlines, uniform line weight, pure white background,
no shading, no hatching, no gray tones, no texture,
large simple closed shapes, centered composition, generous margins

Cada pedazo allí está arreglando algo que salió mal antes.

Línea fina desaparece en la impresora doméstica y la niña no ve dónde parar, daí el thick bold outlines. Sombreado se convierte en lluvia de puntitos en el papel y nadie puede pintar encima, daí el no shading, no gray tones. Región abierta hace que el lápiz de cera se salga, y región demasiado pequeña es pura frustración para la mano de cinco años, daí el large simple closed shapes. Y generous margins porque la impresora de casa no imprime hasta el borde, lo que descubrí de la manera difícil.

Después de eso viene el tema, y allí sí vale capricharse: a friendly dinosaur wearing rain boots, standing next to a puddle.

Deja que la niña elija. Es la mejor parte, y también donde el proceso se atasca, porque la solicitud de la niña siempre tiene un detalle que el modelo ignora o entiende al revés. Genero cuatro de una vez y le dejo que señale. Sale más rápido que intentar acertar de primera, y elegir ya es la mitad del diversión.

La parte que los tutoriales no cuentan

Aquí es donde los vídeos terminan: generaron el PNG, mandaron imprimir, acabó.

Solo que el PNG es el formato equivocado para eso. Una imagen de 1024×1024 impresa en una hoja A4 da unos 90 DPI. La impresora doméstica trabaja entre 300 y 600. El resultado es línea con escalón visible, que es exactamente el problema de los dibujos de banco de imagen que me hizo empezar todo esto.

Generar en resolución mayor ayuda poco y cuesta caro. La salida es otra: trazo negro en fondo blanco no debería ser píxel, debería ser vector.

Son dos operaciones. Primero binarizar, lanzando todo a negro o blanco puro, lo que de paso limpia los grises que el modelo insiste en dejar. Después vectorizar, convirtiendo los contornos en curvas.

# 1. Binarizar: el gris pasa a negro o blanco puro, sin término medio
magick desenho.png -colorspace Gray -threshold 62% -type bilevel desenho.pbm

# 2. Vectorizar: los contornos se convierten en curvas
#    --turdsize   descarta manchitas sueltas (suciedad de la generación)
#    --alphamax   controla cuánto se suavizan las esquinas
potrace desenho.pbm --svg --turdsize 12 --alphamax 1.0 -o desenho.svg

# 3. PDF en A4, listo para imprimir en cualquier tamaño
magick -density 300 desenho.svg -page A4 -gravity center -extent 2480x3508 desenho.pdf

El --threshold 62% es el número que vas a ajustar. Demasiado bajo engorda la línea y cierra los detalles. Demasiado alto rompe el trazo y abre región, que es el peor de los dos, porque el lápiz de cera se sale por un agujero de un píxel solo.

Después del SVG el tamaño de la impresión deja de ser problema. El mismo archivo imprime nítido en A4 o en un panel de metro y medio para la pared del cuarto. Y queda con algunas decenas de KB en vez de megabytes, lo que importa al mandarlo al grupo de padres de la escuela.

La prueba que realmente vale

Ningún número aquí responde si la página sirve. La prueba es dar lápiz de cera a una niña y mirar.

¿Ella ve dónde cierra la línea? ¿Las regiones caben en su mano? ¿El dibujo aguanta ser pintado encima sin convertirse en borrones?

Tiré algunas que quedaron lindas en la pantalla y no funcionaron en el papel. Línea elegante, demasiado fina. Detalle que exigía precisión de adulto. El modelo no tiene cómo saber eso, y ningún prompt lo arregla.

Lo que aún no he medido

Segundos por imagen en cada máquina de la bancada, incluyendo el M4 Max. Cuántas generaciones suelen ser necesarias hasta que salga una página aprovechable, que en mi tarde fue cosa de una en cinco. Y si el klein de 4B pierde contra el hermano de 9B justamente en arte de línea, donde sospecho que el modelo menor va mejor, porque la restricción aquí es simplicidad y no riqueza de detalle.

Esta última es la comparación que quiero hacer. Queda para el próximo.


Fuentes: FLUX.2-klein-4B en Hugging Face · mflux · potrace