WhatsApp

  

Compresión de Imágenes con SVD: Guía Completa y Ejemplos en Python

Aprende a reducir el peso de tus imágenes usando la Descomposición en Valores Singulares (SVD). Incluye teoría, implementación paso a paso en Python, comparativas con JPEG y mejores prácticas.

Compresión de Imágenes con SVD

Una guía práctica, paso a paso, para comprimir imágenes usando la Descomposición en Valores Singulares (SVD) y Python.

1. ¿Qué es la SVD?

La Descomposición en Valores Singulares (Singular Value Decomposition, SVD) es una técnica lineal que factoriza cualquier matriz A en tres matrices:

A = U Σ Vᵀ
  • U: matriz ortogonal (columnas = vectores singulares izquierdos).
  • Σ: matriz diagonal con los valores singulares (ordenados de mayor a menor).
  • Vᵀ: transpuesta de una matriz ortogonal (vectores singulares derechos).

En el contexto de imágenes, A es la matriz de intensidad de píxeles (gris o canal de color). Los valores singulares más grandes capturan la mayor parte de la energía visual; los menores pueden descartarse sin perder calidad perceptual.

2. Principio de Compresión mediante SVD

Al truncar la descomposición a k valores singulares, obtenemos una aproximación de rango k:

Aₖ ≈ Uₖ Σₖ Vₖᵀ

Donde Uₖ tiene k columnas, Σₖ es k×k y Vₖᵀ tiene k filas. El número de datos almacenados se reduce de m·n a k·(m+n+1), logrando compresión.

El factor de compresión (FC) se calcula como:

FC = (m·n) / (k·(m + n + 1))

Elegir k es un compromiso entre calidad y tamaño.

3. Implementación en Python

A continuación, un script completo que carga una imagen, la comprime con SVD y visualiza resultados.

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
def load_image(path, as_gray=True):
    img = Image.open(path)
    if as_gray:
        img = img.convert('L')  # escala de grises
    return np.array(img, dtype=np.float64)
def svd_compress(matrix, k):
    # Descomposición SVD completa
    U, s, VT = np.linalg.svd(matrix, full_matrices=False)
    # Truncado a k componentes
    U_k = U[:, :k]
    s_k = s[:k]
    VT_k = VT[:k, :]
    # Reconstrucción
    return np.dot(U_k, np.dot(np.diag(s_k), VT_k))
def plot_results(original, compressed, k):
    fig, axs = plt.subplots(1, 2, figsize=(10,5))
    axs[0].imshow(original, cmap='gray')
    axs[0].set_title('Original')
    axs[0].axis('off')
    axs[1].imshow(np.clip(compressed, 0, 255), cmap='gray')
    axs[1].set_title(f'Compresión SVD (k={k})')
    axs[1].axis('off')
    plt.tight_layout()
    plt.show()
if __name__ == '__main__':
    img_path = 'ruta/a/tu/imagen.jpg'
    A = load_image(img_path)
    for k in [5, 20, 50, 100]:
        A_k = svd_compress(A, k)
        plot_results(A, A_k, k)

El script permite experimentar con diferentes valores de k y observar el efecto visual inmediato.

4. Comparativa: SVD vs Algoritmos Tradicionales (JPEG, JPEG‑2000)

SVD (Compresión basada en rango)
  • Ventajas: Control fino de calidad, sin artefactos de bloque, ideal para análisis científico.
  • Desventajas: Computacionalmente más costoso (O(mn·min(m,n))) y menos eficiente en hardware especializado.
JPEG (DCT)
  • Ventajas: Amplio soporte, compresión rápida, hardware acelerado.
  • Desventajas: Artefactos de bloque y pérdida de alta frecuencia a altas tasas.
Característica SVD JPEG JPEG‑2000
Tipo de compresiónLossy (controlable por k)Lossy (cuantización)Lossy / Lossless
Artefactos típicosNinguno (solo suavizado)Bloques, ringingBlur, ringing
Velocidad de compresiónMedia‑Alta (SVD completa)AltaMedia
EscalabilidadExcelente (incrementar k)LimitadaBuena
Uso en visión por computadoraAlto (preserva estructura)ModeradoAlto

5. Buenas Prácticas y Optimización

  • Pre‑procesado: Normaliza la imagen a float64 y centra los valores (resta la media) para mejorar la convergencia de SVD.
  • Selección de k: Analiza la energía acumulada: cum_energy = np.cumsum(s) / np.sum(s). Elige el menor k que supere, por ejemplo, el 90 % de energía.
  • Uso de SVD truncada: En lugar de calcular la SVD completa, emplea scipy.sparse.linalg.svds para obtener sólo los k valores más grandes, reduciendo tiempo y memoria.
  • Paralelismo: Para imágenes muy grandes, divide la matriz en bloques y procesa cada bloque en paralelo (multiprocessing o Dask).
  • Formato de salida: Guarda la representación comprimida como .npz (U_k, s_k, VT_k) y reconstruye bajo demanda, evitando la generación de archivos JPEG.

6. Solución de Problemas Comunes

Problema: Memoria insuficiente al cargar imágenes de alta resolución.

Solución: Usa numpy.memmap o procesa la imagen en tiles (p.ej., 1024×1024) y combina los resultados.

Problema: La imagen reconstruida aparece más oscura.

Solución: Asegúrate de volver a añadir la media que se restó durante la normalización y de clipear los valores al rango [0,255] antes de guardar.

Problema: Tiempo de compresión excesivo (> minutes).

Solución: Cambia a SVD truncada (scipy.sparse.linalg.svds) y/o reduce la resolución temporalmente con cv2.resize antes de comprimir.

7. Casos de Uso Reales

  • Investigación médica: Compresión de imágenes de resonancia magnética donde la preservación de detalles finos es crítica.
  • Visión por computadora en drones: Transmisión de frames comprimidos con SVD para reducir ancho de banda sin sacrificar detección de objetos.
  • Almacenamiento de catálogos astronómicos: Reducción de petabytes de imágenes del cielo manteniendo la fidelidad espectral.

© 2025 BlogTech – Todos los derechos reservados.



Compresión de Imágenes con SVD: Guía Completa y Ejemplos en Python
ASIMOV Ingeniería S. de R.L. de C.V., Emiliano Nava 13 noviembre, 2025
Compartir
Iniciar sesión dejar un comentario

  
Clustering Espectral: Conceptos, Implementación en Python y Comparativas Prácticas
Guía completa sobre el algoritmo de clustering espectral, su teoría, paso a paso, ejemplos en Python y comparativas con otras técnicas de clustering.