Saltar al contenido

2026-09-01

Conceptos de compresión de imágenes: convoluciones, bajo rango y lossy vs. lossless

Esta nota explica los tres conceptos que sostienen lic-lab, mi banco de pruebas de compresión de imágenes aprendida (learned image compression): cómo las convoluciones aprenden a comprimir, qué son las aproximaciones de bajo rango, y por qué "lossy" y "lossless" no son dos técnicas rivales sino dos capas de un mismo pipeline.

Convoluciones como codificador y decodificador

En un códec aprendido, dos redes convolucionales hacen el trabajo que en JPEG hace la transformada DCT: la transformada de análisis (gₐ) convierte la imagen en una representación latente más compacta, y la transformada de síntesis (g_s) la reconstruye de vuelta a píxeles.

gₐ: (B, 3, H, W)  →  (B, M, H/16, W/16)      # imagen → latente y
g_s: (B, M, h, w)  →  (B, 3, H, W)            # latente ŷ → imagen reconstruida

gₐ apila varias convoluciones con stride 2, reduciendo la resolución espacial en cada capa (H/16 tras 4 etapas) mientras aumenta el número de canales — igual que una CNN de clasificación, pero sin capas totalmente conectadas al final: la salida sigue siendo un mapa espacial, solo que mucho más chico y con muchos más canales (M = 192 o 320 en los modelos que replico). En vez de ReLU, estas capas usan GDN (Generalized Divisive Normalization) — una no linealidad diseñada específicamente para imágenes naturales, que normaliza cada canal dividiendo por una combinación aprendida de la energía de los canales vecinos, y que empíricamente da mejores curvas rate-distortion que ReLU/GDN en este dominio.

Los modelos más recientes (gmm_attn, tcm) añaden bloques residuales y, en el caso de tcm, una rama con atención en ventanas (estilo Swin) en paralelo a la rama convolucional — la misma idea de Transformers aplicada aquí a nivel de parche de imagen, no de token de texto.

Aproximaciones de bajo rango

Una imagen (o un parche, o los pesos de una capa) es una matriz X. La idea del bajo rango es que gran parte de esa matriz es información redundante, y se puede aproximar con el producto de dos matrices mucho más chicas:

X (n×n)  ≈  U (n×r) · Vᵀ (r×n)         donde r ≪ n

En vez de guardar n² números, se guardan 2·n·r — y cuanto menor el rango r, mayor la compresión (y mayor la pérdida de detalle).

≈×→

X (parche 8×8) se factoriza en U (8×2) por V (2×8) — rango 2. Su producto (derecha, pulsando) es una aproximación de X, no una copia exacta: guarda 32 números en vez de 64, a cambio de perder algo de detalle.

lic-lab implementa tres variantes de esta idea:

  • SVD truncada — la descomposición clásica en valores singulares, quedándose solo con los r componentes de mayor energía. Es el baseline de referencia contra el que se comparan las demás.
  • QMF (Quantization-aware Matrix Factorization) — en vez de factores continuos, restringe U y V a enteros acotados (int8, rango [-128, 127]), optimizados con BCD (block coordinate descent: se fija una matriz, se resuelve la otra en forma cerrada, y se alterna) inicializado con la SVD truncada. Al ser enteros desde el diseño, los factores se codifican directamente como imágenes de 8 bits sin pérdida adicional — es una técnica pensada para producir un bitstream real, no solo para aproximar.
  • LLoRMA (bajo rango local) — en vez de una única SVD global sobre toda la imagen, agrupa regiones similares con k-means y les aplica SVD por separado a cada clúster. La idea es que distintas zonas de una imagen (cielo liso vs. textura de una hoja) tienen estructuras de rango muy distintas, y forzarlas a compartir un único rango global desperdicia capacidad.

En lic-lab estos operadores no compiten solo contra JPEG: también se aplican sobre el latente y de un modelo hyperprior (en vez de, o además de, la cuantización escalar habitual), y sobre los pesos de gₐ/g_s para comprimir el modelo mismo, no la imagen.

Compresión con pérdida (lossy) vs. sin pérdida (lossless)

Es fácil pensar que "lossy" y "lossless" son dos categorías de formato (JPEG vs. PNG), pero en un códec aprendido moderno conviven en el mismo pipeline, en dos pasos distintos:

  1. La pérdida ocurre en la cuantización. El latente y que produce gₐ es continuo (números reales). Para poder transmitirlo hace falta discretizarlo a ŷ — ahí, y solo ahí, se pierde información irrecuperablemente. lic-lab prueba tres estrategias de cuantización en entrenamiento (ruido uniforme aditivo, straight-through estimator, redondeo round(y−μ)+μ), porque el redondeo no es diferenciable y hay que aproximarlo de alguna forma para poder entrenar con descenso de gradiente.
  2. La codificación de ese resultado ya discreto es sin pérdida. Una vez que ŷ son enteros, convertirlos a bytes es un problema de codificación entrópica — y ahí no se pierde nada más: un codificador rANS (o aritmético) usa las probabilidades que predice el modelo de entropía (factorizado, gaussiano condicional, o una mezcla de gaussianas) para asignar menos bits a los valores más probables. decompress( compress(x)) tiene que ser bit-exacto — ese es el invariante que se testea en cada módulo de entropía nuevo antes de aceptarlo en el repo.

En otras palabras: toda la pérdida de un códec aprendido vive en un único punto (la cuantización), y todo lo que pasa después — incluida la factorización de bajo rango de QMF, cuyos factores enteros también se codifican sin pérdida adicional — es compresión sin pérdida sobre una representación que ya es, deliberadamente, una versión con pérdida de la imagen original.

Esto es lo mismo que hace JPEG clásico, solo que con una transformada aprendida en vez de la DCT fija: DCT → cuantización (con pérdida, ahí está el parámetro de calidad) → Huffman (sin pérdida). La diferencia de fondo es que en un códec aprendido tanto la transformada como el modelo de probabilidad que alimenta al codificador entrópico se entrenan de punta a punta para minimizar la distorsión a una tasa de bits dada — en vez de estar fijados de antemano por un estándar.

Cómo se mide si vale la pena la pérdida

lic-lab reporta cada modelo como un punto en una curva rate-distortion (RD): bits por píxel (bpp) en el eje x, PSNR o MS-SSIM en el eje y. Un modelo es mejor que otro si, a la misma tasa de bits, reconstruye con menos distorsión — y esa curva se compara siempre primero contra JPEG, JPEG2000, WebP, BPG y SVD truncada como baselines clásicos, sobre el dataset Kodak (el mismo que usan los papers originales), para que la comparación sea real y no un número aislado.


Ver también: overview del proyecto lic-lab, fundamentos de CNN y fundamentos de Transformers.