Alejandro José Hugo Escalante Santos
Excelente curso.
Daniel Erazo
ProfesorMuchas gracias, me alegro que te haya gustado!
La compresión de imágenes con SVD te permite reducir el tamaño de una foto conservando su estructura visual, usando solo los componentes más importantes de su descomposición matricial. Aprenderás a aplicarlo en Python con scikit-image y NumPy, una técnica clave si trabajas en machine learning y necesitas datasets más ligeros.
La idea central es tratar una imagen como una matriz de píxeles, descomponerla con Singular Value Decomposition y reconstruirla con solo los K valores singulares más representativos. Lo demás, en muchos casos, es ruido.
¿Por qué funciona SVD para comprimir imágenes?
Una imagen en escala de grises es, en esencia, una matriz numérica donde cada celda guarda la intensidad de un píxel. Al aplicar SVD, esa matriz se descompone en tres: U, Sigma y V transpuesta [0:30].
La matriz Sigma contiene los valores singulares ordenados de mayor a menor importancia. Los primeros valores capturan la estructura principal: formas, contrastes, bordes. Los últimos suelen representar ruido o detalles muy finos.
¿Qué es un valor singular en SVD? Es un número que mide cuánta información aporta cada componente de la descomposición. Mientras más alto, más relevante es ese componente para reconstruir la imagen original.
Descartando los componentes menos relevantes y reconstruyendo con los K más importantes, obtienes una imagen casi idéntica usando muchísima menos información.
¿Cómo aplicar SVD a una imagen en Python?
El primer paso es preparar la imagen. SVD no trabaja directamente con imágenes a color, así que necesitas convertirlas a escala de grises y opcionalmente redimensionarlas para que el cómputo sea más rápido [2:15].
Desde skimage importas tres piezas clave:
data para acceder a imágenes de prueba.resize desde skimage.transform para ajustar dimensiones.rgb2gray desde skimage.color para pasar a escala de grises.Una vez tienes la imagen como matriz, la redimensionas a 300 por 200 píxeles para manejarla con eficiencia y aplicas la descomposición:
python U, S, Vt = np.linalg.svd(imagen)
Esto te devuelve U con forma 300 por 300, un vector S con 200 valores singulares y Vt con forma 200 por 200 [3:45].
¿Cómo reconstruir la imagen con K componentes?
La reconstrucción consiste en quedarte solo con las primeras K columnas de U, los primeros K valores singulares de S (convertidos a matriz diagonal con np.diag) y las primeras K filas de Vt. Después multiplicas las tres:
python def reconstruir_con_k(k): U_k = U[:, :k] S_k = np.diag(S[:k]) Vt_k = Vt[:k, :] return U_k @ S_k @ Vt_k
Probando con valores K de 5, 20 y 50, y graficando con matplotlib en una rejilla de subplots, puedes comparar visualmente cómo crece la fidelidad a medida que sumas componentes [5:50].
¿Qué resultados obtienes al variar el valor de K?
En el ejemplo de un cohete, la reconstrucción cuenta una historia clara:
Y aquí viene lo interesante: pasaste de necesitar 60.000 números (300 x 200 píxeles) a representar la misma imagen con apenas 50 valores singulares. Eso es una compresión cercana a seis veces.
¿Cuántos valores singulares necesito para una buena reconstrucción? Depende de la imagen, pero entre el 10% y el 25% de los valores totales suele ser suficiente para conservar la estructura visual reconocible.
¿Qué beneficios tiene la compresión SVD en machine learning?
Reducir dimensiones con SVD no es solo un truco visual, tiene impacto directo en el rendimiento de tus modelos.
Eficiencia en almacenamiento y velocidad
Pasar de 60.000 valores a 50 por imagen ahorra gigabytes cuando trabajas con datasets de millones de imágenes. Los tiempos de carga y procesamiento se aceleran de forma drástica [9:20].
Aceleración del entrenamiento
Si alimentas tu modelo con 50 valores singulares en lugar de 60.000 píxeles por imagen, el entrenamiento es muchísimo más rápido. Conservas la esencia de la información sin cargar al modelo con detalles redundantes.
Eliminación de ruido o denoising
Los componentes con valores singulares más pequeños suelen capturar grano de la imagen o imperfecciones del sensor. Al descartarlos, aplicas un filtrado automático de ruido que ayuda a que los modelos generalicen mejor, aprendiendo la estructura fundamental en lugar de memorizar imperfecciones específicas [10:40].
¿Cuál es el K mínimo para reconocer una imagen?
Este es el reto práctico: vuelve a ejecutar el código con distintos valores de K y descubre cuál es el mínimo con el que todavía identificas claramente el objeto. Comparte tu valor y una captura de pantalla en los comentarios para comparar resultados con otros estudiantes.
Hola Chicos X2. Aqui estoy de nuevo con este, el codigo mejorado del reto. "Gemini me ayudo un poco, lo acepeto, Yo tambien se programar bien solo fue una AI code help" \n este ejemplo es mas bonito.
import numpy as np import matplotlib.pyplot as plt from skimage import data from skimage.transform import resize from skimage.color import rgb2gray def run_svd_analysis(): # 1. Preprocesamiento: Cargar imagen y convertir a escala de grises # Usamos data.cat() como en tu ejemplo original_img = rgb2gray(data.cat()) image = resize(original_img, (300, 200)) # 2. Descomposición SVD # A = U * Sigma * V^T U, S, VT = np.linalg.svd(image, full_matrices=False) # 3. Configuración de parámetros (Primeros 7 términos de Fibonacci) k_values = [1, 2, 3, 5, 8, 13, 21] # --- VISUALIZACIÓN DE IMÁGENES RECONSTRUIDAS --- # Creamos un layout de 2x4 (8 espacios: 1 para original + 7 para k_values) fig, axes = plt.subplots(2, 4, figsize=(16, 10)) axes = axes.flatten() # Aplanamos para iterar fácilmente # Espacio 0: Imagen Original axes[0].imshow(image, cmap='gray') axes[0].set_title("Original (Full Rank)", fontsize=10, fontweight='bold') axes[0].axis('off') # Espacios 1-7: Reconstrucciones for i, k in enumerate(k_values): # Reconstrucción de bajo rango (Rank-k Approximation) # Rebuilt = U_k * Sigma_k * V^T_k rebuilt_img = U[:, :k] @ np.diag(S[:k]) @ VT[:k, :] idx = i + 1 axes[idx].imshow(rebuilt_img, cmap='gray') axes[idx].set_title(f"Rebuilt k={k} (Fibonacci)", fontsize=10) axes[idx].axis('off') plt.suptitle("Image Compression via Singular Value Decomposition (SVD)", fontsize=16) plt.tight_layout() # --- VISUALIZACIÓN DE VALORES SINGULARES (SIGMA) --- plt.figure(figsize=(10, 5)) plt.plot(S, color='crimson', lw=2, label='Singular Values ($\sigma_i$)') # Resaltar los valores de k usados (Fibonacci) plt.scatter(k_values, S[k_values], color='blue', zorder=5, label='k-points used') plt.title("Decaimiento de la Energía (Valores Singulares)", fontsize=14) plt.xlabel("Índice del Valor Singular ($i$)") plt.ylabel("Magnitud ($\sigma_i$)") plt.yscale('log') # Escala logarítmica para ver mejor el decaimiento plt.grid(True, which="both", ls="-", alpha=0.5) plt.legend() plt.show() if __name__ == "__main__": run_svd_analysis()
Este es el primer output :
Yo he querido que los vlaores k sigan la secuencia de Fibonacci proque es fantastica en progrmaacion y me gusta ver en que punto el Gato se ve mejor como el gato de lai magne original para un valor k?.
Observa la gráfica pseudo-Log de los valores singulares. El punto donde la curva se vuelve casi plana (el "codo") te indica cuánta información es realmente necesaria para representar la imagen. Con $k=21$, verás que ya se distingue perfectamente al gato, ¡a pesar de que la matriz original tiene rango 200! Estás comprimiendo la información casi un 90%.
Aproximación de Bajo Rango: Matemáticamente, lo que estás haciendo es el Teorema de Eckart-Young-Mirsky, que dice que la mejor aproximación de rango $k$ de una matriz (en norma de Frobenius) es precisamente la que obtienes truncando la SVD.
El valor optimo de k para convervar la mayor informacion psible de la imagen original esta entre [13 , 21 ] , tal vez sea 16 -> 2**4 l ocual hace sentido.
\nMuchas Gracias al Profesor @Daniel pro tan buen curso, los tres han sido geniales, fue un todo un viaje de nuevo que he pasado , Yo ya habia visto Algebra Lienal I,II en la Universidad con Matlab, ahora l ohe vuelto a entender mejro y con ayuda de Python es mas bonito.
print("Nunca pares de Aprender")
Alejandro José Hugo Escalante Santos
Excelente curso.
Daniel Erazo
ProfesorMuchas gracias, me alegro que te haya gustado!
Bryan Castano
Emilio José Chaparro Barrera
En este caso cada componente es un fragmento de una única imagen, en PCA aplicado a eigen faces cada componente una eigenface que pueden construir múltiples caras. Pero SVD también es aplicable a eigenfaces, solo que ya no con img ej. 64x64 px sino ej. 1920x1080 px. En SVD la matriz U es los eigenvectores de la matrix de covarianza A@A.T y serán las eigenfaces.
Emilio José Chaparro Barrera
Ademas al final nombrando el Denoising seria posible pasar una img pixelada vieja y dejarla sin ruido, teniendo como resultado algo mas nitido, eliminando componentes.
Gabriel Obregón
🧮🖼️ Compresión de Imágenes con SVD en Python
🎯✨ IDEA PRINCIPAL
La descomposición en valores singulares (SVD) es una técnica para:
✔️ Comprimir imágenes
✔️ Reducir ruido
✔️ Mantener la estructura visual esencial
🔑 Se conserva solo la información más importante de la imagen.
Resultado final: 📉 Menos datos | ⚡ Más velocidad | 👁️ Buena calidad visual
🧠🔍 ¿QUÉ ES SVD?
Una imagen en escala de grises se representa como una matriz numérica.
Al aplicar SVD, la imagen se separa en tres componentes:
▶️ U → estructura principal
▶️ Σ (S) → valores singulares (importancia)
▶️ Vᵀ (VT) → estructura complementaria
📐 Relación fundamental:
imagen ≈ U × Σ × V transpuesta
🔝 Valores grandes → formas y contrastes principales 🔻 Valores pequeños → ruido y detalles finos
🖼️⚙️ TRATAMIENTO DE LA IMAGEN
✔️ Conversión a escala de grises
✔️ Uso de una sola matriz (no RGB)
✔️ Redimensionado para eficiencia
📏 Ejemplo usado:
· Tamaño: 300 × 200 píxeles
· Total original: 60 000 valores
📐📊 DIMENSIONES TRAS SVD
Para una imagen de 300 × 200:
🧩 U → 300 × 300
🧩 S → 200 valores singulares
🧩 Vᵀ → 200 × 200
📌 Estas dimensiones permiten reconstruir la imagen usando solo una parte de la información.
🔄🧱 PROCESO DE COMPRESIÓN
1️⃣ Convertir a escala de grises
2️⃣ Redimensionar la imagen
3️⃣ Aplicar SVD
4️⃣ Elegir k valores singulares
5️⃣ Reconstruir la imagen
6️⃣ Evaluar calidad vs. compresión
🧠 Menos k → más compresión 👁️ Más k → más calidad
🧩🔢 RECONSTRUCCIÓN CON k
Para reconstruir:
🔹 Primeras k columnas de U
🔹 Primeros k valores de S
🔹 Primeras k filas de Vᵀ
📦 Solo se conserva la información más relevante.
Hola Chicos, Yo os comparto algunas notas y outputs de mi tutot de LinAlg "Gemini" que es genial en su modo "learning".
Si el Eigendecomposition Av = lambda .v es como entender el ADN de una matriz cuadrada, la Descomposición en Valores Singulares (SVD) es como hacerle una radiografía completa a cualquier matriz, sea cuadrada o no.
La SVD establece que cualquier matriz $A$ de dimensiones $m x n$ puede ser factorizada en el producto de tres matrices especiales:
$$A = U \Sigma V^T$$
Donde:
@Aqui un script de ejempl oque Gemini me ha dado :
import numpy as np import matplotlib.pyplot as plt def svd_compression_demo(): # 1. Crear una matriz de 100x100 con un patrón (nuestra "imagen") # Usamos un producto exterior para crear una matriz de bajo rango x = np.linspace(-5, 5, 100) y = np.linspace(-5, 5, 100) X, Y = np.meshgrid(x, y) A = np.sin(X) + np.cos(Y) # Un patrón complejo # 2. Aplicar SVD # U: Vectores izquierdos, s: Valores singulares, Vt: Vectores derechos U, s, Vt = np.linalg.svd(A) # 3. Reconstrucción con diferentes rangos (k) # k es el número de valores singulares que decidimos mantener ranks = [2, 5, 10, 50] plt.figure(figsize=(12, 8)) # Imagen Original plt.subplot(2, 3, 1) plt.imshow(A, cmap='viridis') plt.title("Original (Rango 100)") plt.axis('off') for i, k in enumerate(ranks): # Reconstrucción: U[:, :k] @ Sigma[:k, :k] @ Vt[:k, :] # En numpy, 's' es un vector, lo convertimos a diagonal A_approx = U[:, :k] @ np.diag(s[:k]) @ Vt[:k, :] plt.subplot(2, 3, i + 2) plt.imshow(A_approx, cmap='viridis') plt.title(f"Reconstrucción con k={k}") plt.axis('off') plt.tight_layout() plt.show() # Mostrar la importancia de los valores singulares plt.figure(figsize=(6, 4)) plt.plot(s, 'ro-', markersize=2) plt.title("Magnitud de los Valores Singulares ($\sigma$)") plt.xlabel("Índice") plt.ylabel("Valor") plt.grid(True) plt.show() if __name__ == "__main__": svd_compression_demo()
recuerda siempre la conexión sagrada entre SVD y los Eigenvalores:
Much ode esto ha sido expliicado por el profesor durante esgte curso, por tanto si Gemini y @Daniel dicen l omismo es por la plena real.