Cómo crear códigos QR con Stable Diffusion

Crea códigos QR decorativos, profesionales y 100% funcionales mediante Stable Diffusion y ControlNet.

Introducción

Hace poco más de un mes, un usuario de Reddit jugó con la idea de generar códigos QR con Stable Diffusion mediante el uso de ControlNet. Con esta técnica se pretendía condicionar la generación de imágenes de manera que Stable Diffusion genera una imagen creativa y atractiva mientras que ControlNet se encarga de mantener la estructura lo más intacta posible para mantener la legibilidad del código QR. Sin duda una gran idea.

En cuestión de horas empezaron a publicarse nuevos métodos y formas de generar códigos QR con Stable Diffusion. La mayoría de resultados son sorprendentes pero en mi opinión hay 2 problemas importantes.

El primer problema es que las imágenes generadas son tan impactantes que ya nisiquiera parecen códigos QR. Cuando vemos un código de barras de una bolsa de almendras o un código QR en la mesa de un restaurante, inmediatamente sabemos para qué sirven y qué hacer con ellos. Al ver estas imágenes no tendremos esa familiaridad.

En segundo lugar, y más importante todavía, es el hecho de que la mayoría de estos códigos QR no son escaneables. Inicias la aplicación de cámara, apuntas al código y no ocurre nada. Se ha alterado tanto la imagen que ya no hay información codificada en forma de código QR.

En este articulo veremos un sencillo método para alterar el código QR con Stable Diffusion y ControlNet. Después utilizaremos un script para filtrar las imágenes que ofrezcan total compatibilidad y que funcionen con todas las aplicaciones de escaneo de códigos QR.

El resultado son imágenes como estas:

¡Más abajo encontrarás más ejemplos!

Detalles técnicos del código QR

El código QR fue creado en 1994 por la compañía japonesa Denso Wave. Su trabajo se volvió tan popular y útil que se estandarizó internacionalmente bajo la norma ISO/IEC 18004. En esta norma se establecen las especificaciones técnicas y los requisitos para la creación y lectura de estos códigos.

La especificación sirve para que individuos y empresas implementen todos estos detalles e inventen librerías de software capaces de crear, leer e interpretar estos códigos. No todas las implementaciones son iguales, de ahí que algunos de estos códigos solo puedan leerse con ciertas aplicaciones de lectura de códigos QR. Por lo tanto, no tiene sentido que para poder leerlo tengas que descargar una nueva aplicación. La principal ventaja de los códigos QR es la compatibilidad.

Evitando la corrupción de datos

Los códigos QR poseen una importante característica llamada correción de errores.

Imagina un paquete que atraviesa el mundo para llegar a su destino. Es bastante probable que este código QR pegado en el lateral pueda sufrir daños o alteraciones. Por este motivo cuando se crea el código la información se codifica de manera redundante. Es decir, se duplican datos para que si una parte del código se ha dañado, la información todavía esté codificada en otro lugar y pueda ser leída.

Hay 4 niveles de correción de error: L, M, Q y H. Estos niveles toleran errores de hasta un 7%, 15%, 25% y 30%, respectivamente.

Cuando creamos un código QR con Stable Diffusion lo que estamos haciendo es simplemente destruir parte del código original para reemplazarlo por elementos visualmente atractivos. Por lo tanto, es imprescindible utilizar una correción de error del 30% (nivel H) y no sobrepasar el límite o el código no podrá ser leído y perderá todo su propósito.

Creación del código QR

Lo primero es generar un código QR con la información que queremos codificar. Puedes utilizar una de las muchas webs que ofrecen este servicio pero aquí tienes la posibilidad de crearlo sin salir de este artículo.

Ten en cuenta que cuanto mayor sea la longitud del texto o URL, más datos tendrán que codificarse en la imagen. Esto hará que el código QR contenga más partes negras y cuando Stable Diffusion destruya una zona, destruirá más datos por lo que es posible que el código QR no pueda ser leído. Observa como cambia el código QR a medida que se incrementa el número de caracteres.

Código QR
Texto "1234567890" repetido 1 vez
Código QR
Texto "1234567890" repetido 3 veces
Código QR
Texto "1234567890" repetido 9 veces
Código QR
Texto "1234567890" repetido 27 veces

Si vas a introducir una URL muy larga te recomiendo que la acortes utilizando servicios como bit.ly.

Los códigos QR aquí generados se crean con una correción de error nivel H. Puedes modificar algunos parámetros aunque te recomiendo dejarlos como están por defecto.

Tamaño:

Modificación del código QR

En este punto doy por hecho que tienes instalado ControlNet. De no ser así, realiza este paso primero.

Instalando el modelo

Muchos artículos utilizan dos unidades de ControlNet: una unidad con el modelo control_v11f1e_sd15_tile y otra unidad con el modelo control_v1p_sd15_brightness. Esta configuración ofrece resultados impresionantes pero el escaneo no suele funcionar y los códigos dejan de parecer códigos.

En este caso vamos a utilizar una única unidad de ControlNet cargada con el modelo control_v1p_sd15_qrcode.

Descarga este modelo (archivo .safetensors) y su configuración (archivo .yaml con el mismo nombre) del siguiente repositorio de HuggingFace: https://huggingface.co/DionTimmer/controlnet_qrcode.

Introduce estos dos archivos en la carpeta models/ControlNet/ que encontrarás dentro del directorio donde tienes instalado Automatic1111.

  1. automatic1111
    1. models
      1. ControlNet
        1. control_v1p_sd15_qrcode.safetensors
        2. control_v1p_sd15_qrcode.yaml

Muchas gracias a Dion Timmer por crear este fantástico modelo.

Si deseas utilizar un modelo de Stable Diffusion 2.1 puedes descargar control_v11p_sd21_qrcode en lugar de la versión 1.5.

Parámetros de configuración

Con el código QR original y el modelo de ControlNet instalado correctamente, procedemos a iniciar Automatic1111 y accedemos a la pestaña img2img.

captura de pantalla con la configuración
Captura de pantalla mostrando los parámetros utilizados en Automatic1111

Los parámetros que debemos configurar son:

  • Checkpoint: A tu gusto. Recomendación: dreamshaper_631BakedVae.safetensors. Recuerda utilizar un modelo 1.5 si utilizas control_v1p_sd15_qrcode o un modelo 2.1 en caso de utilizar control_v1p_sd21_qrcode.
  • Positive prompt: No hace falta que sea muy largo ni específico como verás en los ejemplos más abajo. Algunos prompts son mas agresivos y destruyen más partes del código, por lo que tendrás que regular otros valores.
  • Negative prompt: Lo mismo que el positivo, introduce algo básico como ugly, disfigured, low quality, blurry, nsfw, watermark, text.
  • Pestaña img2img: Selecciona la imagen del código QR que has generado.
  • Width / Height: El valor que hayas seleccionado al crear el código QR. Un valor de 512x512 debería ser suficiente.
  • Denoising strength: Este valor es tal vez el más importante. El valor óptimo suele estar en 0.58 aunque si tu prompt está destruyendo demasiado código QR puedes bajarlo hasta 0.55. Si el código QR apenas cambia su diseño, puedes subirlo hasta 0.65. Fuera de esos valores no tendrás mucha suerte.

El resto de parámetros puedes dejarlos por defecto. Yo he utilizado los siguientes:

  • Sampling method: Euler A.
  • Sampling steps: 30.
  • CFG Scale: 7.

En cuanto al desplegable de configuración de ControlNet, debes configurar la unidad 0 (la primera) de la siguiente forma:

  • Single Image: Selecciona de nuevo la imagen del código QR original.
  • Enable: True. Activa la unidad o no hará nada.
  • Pixel Perfect: True. Activa esta opción.
  • Control Type: All. Déjalo como está por defecto.
  • Preprocessor: none. No hay que preprocesar el código QR.
  • Model: Selecciona control_v1p_sd15_qrcode. En mi caso estoy utilizando el modelo con hash: 9c780d03, pero esto no debería importar.
  • Control Weight: El valor por defecto de 1 está bien. Entre 0.9 y 1.3 también hay buenos resultados pero solo es útil cuando quieras afinar al máximo el resultado.
  • Starting Control Step: 0. Dejamos que ControlNet condicione la imagen desde el principio de la generación.
  • Ending Control Step: 0.9. Esto significa que ControlNet condicionará el resultado hasta que la generación haya llegado al 90%. El 10% restante dará a Stable Diffusion libertad total para que refine los detalles como le apetezca. Si ves que tu prompt está destruyendo demasiada información del código QR puedes subirlo hasta 1. Así ControlNet intentará preservar el código QR hasta el final.
  • Control Mode: Balanced.
  • Resize Mode: Innecesario si es del mismo tamaño. Puedes dejarlo en Just Resize.

Tras esta configuración iniciamos la generación y obtendremos nuestro código QR generado con Stable Diffusion.

Resultados

A continuación unos cuantos ejemplos de códigos QR que he generado para que compares los resultados.

Recuerda que gracias a la técnica de outpainting puedes seguir mejorando la imagen para que el código QR quede integrado en algo más amplio.

Comprobación de códigos QR

Muchos códigos QR funcionarán, otros no, y otros solo con determinadas aplicaciones.

Te ofrezco dos maneras de comprobar que el código funciona: una manual y una automática.

Comprobación manual

Puedes utilizar la siguiente herramienta para comprobar el código QR desde este artículo. No es perfecta pero es una manera rápida de comprobar un código QR (a veces un código válido puede aparecer como inválido).

El código QR se comprueba en tu navegador. El archivo de imagen no se sube a ningún servidor.

Comprobación automática

Para mejorar el proceso de comprobación aquí tienes un script en Python que utiliza 3 librerías distintas de lectura de códigos QR para filtrar los códigos que sean válidos en todas las librerías a la vez.

Este método es más fiable que el manual ya que cada código se comprueba 3 veces, pero también se desecharán más códigos QR por no tener compatibilidad total (es lo que buscamos, ¿no?).

check.py
  • Python
import os
import sys
import glob
import shutil
import cv2
from pyzbar import pyzbar
import zxing

if len(sys.argv) < 2 or not sys.argv[1]:
  print('Missing first argument (text or url)')
  print('Usage: python check.py "https://www.felixsanz.dev"')
  sys.exit()

def read_qr_code_with_cv2(file):
  try:
    detector = cv2.QRCodeDetector()
    img = cv2.imread(file)

    value = detector.detectAndDecode(img)[0]

    return value
  except:
    return

def read_qr_code_with_pyzbar(file):
  try:
    img = cv2.imread(file)

    value = pyzbar.decode(img)[0].data.decode()

    return value 
  except:
    return

def read_qr_code_with_zxing(file):
  try:
    detector = zxing.BarCodeReader()
    value = detector.decode(file).parsed

    return value
  except:
    return

PASS = '\033[32m'
FAIL = '\033[31m'
RESET = '\033[0m'

text = sys.argv[1]

for file in glob.glob('./images/*.png'):
  cv2_code = read_qr_code_with_cv2(file)
  cv2_result = (cv2_code == text)
  cv2_color = PASS if cv2_result else FAIL

  pyzbar_code = read_qr_code_with_pyzbar(file)
  pyzbar_result = (pyzbar_code == text)
  pyzbar_color = PASS if pyzbar_result else FAIL

  zxing_code = read_qr_code_with_zxing(file)
  zxing_result = (zxing_code == text)
  zxing_color = PASS if zxing_result else FAIL

  print(f'[{cv2_color}cv2{RESET} {pyzbar_color}pyzbar{RESET} {zxing_color}zxing{RESET}] {file}')

  if (cv2_result and pyzbar_result and zxing_result):
    shutil.copy2(file, file.replace('/images/', '/valid/'))

El script funciona de la siguiente manera:

  1. Se encarga de leer las imágenes .png que hay dentro de la carpeta ./images.
  2. Comprueba la validez del código QR mediante las librerías opencv-python, pyzbar y zxing. Debes pasar como primer argumento (y único) el texto o URL con el que creaste el código QR, para que se compruebe que el resultado de la lectura es el mismo.
  3. Si el código QR es válido en las 3 implementaciones, el script copia la imagen a la carpeta ./valid.

Para instalar este script clona el repositorio https://github.com/felixsanz/felixsanz_dev, accede a la carpeta de este artículo, inicia un entorno virtual e instala las dependencias:

git clone https://github.com/felixsanz/felixsanz_dev
cd felixsanz_dev/articles/how-to-create-qr-codes-with-stable-diffusion

python -m venv .venv

source .venv/bin/activate # Unix
.venv\Scripts\activate # Windows

pip install -r requirements.txt

A continuación copia las imágenes .png de los códigos QR que quieras comprobar en la carpeta ./images. Añade todos los que has generado, ¡sin miedo!

Ejecuta el script, obtendrás estos resultados:

python check.py "https://www.felixsanz.dev"
[cv2 pyzbar zxing] ./images/00218-2724904587.png
[cv2 pyzbar zxing] ./images/00235-4081443668.png
[cv2 pyzbar zxing] ./images/00159-2755401775.png
[cv2 pyzbar zxing] ./images/00130-3223553027.png
[cv2 pyzbar zxing] ./images/00029-3235345478.png

Los nombres de las librerías aparecen en verde o rojo dependiendo del resultado de la librería. Cuando una imagen muestre las 3 librerías en color verde, se copiará a la carpeta ./valid.

  1. .venv
  2. check.py
  3. images
    1. 00218-2724904587.png
    2. 00235-4081443668.png
    3. 00159-2755401775.png
    4. 00130-3223553027.png
    5. 00029-3235345478.png
  4. requirements.txt
  5. valid
    1. 00235-4081443668.png
    2. 00130-3223553027.png

Conclusión

En este artículo hemos visto los principales problemas que tienen los métodos actuales de generación de códigos QR con Stable Diffusion, mediante el uso de dos modelos de ControlNet. También vimos los detalles técnicos imprescindibles para mejorar la compatibilidad de los códigos QR.

Y por último hemos aprovechado toda esta información para generar códigos QR con Stable Diffusion mediante un único modelo de ControlNet que no destruye tanto la información codificada en el código QR.

Con todo esto y los métodos de comprobación espero que puedas generar muchos códigos QR espectaculares y funcionales. ¡Toca el emoji para celebrarlo!

Etiquétame en las redes sociales si compartes estos códigos QR ya que estaré encantado de verlos.

Puedes apoyarme para que pueda dedicar aún más tiempo a escribir artículos y tener recursos para crear nuevos proyectos. ¡Gracias!