La descomposición en valores singulares (SVD) es una técnica matemática potente que nos permite reducir la dimensionalidad de una matriz sin perder información esencial. A menudo, se aplica en el procesamiento de imágenes para comprimir archivos manteniendo una buena calidad visual. Pero, ¿cómo aplicamos esta técnica a una imagen concreta? Veamos el proceso completo y cómo esto afecta la reconstrucción de la imagen.
¿Qué librerías son esenciales para el procesamiento de imágenes?
Para comenzar con nuestro análisis, es necesario importar las librerías adecuadas. Utilizaremos principalmente matplotlib para graficar y tratar imágenes, y numpy para manejar números y realizar operaciones matemáticas:
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
Estas librerías nos permitirán cargar, manipular y visualizar nuestra imagen de manera eficiente.
¿Cómo cargar y preparar la imagen?
Primero, cargamos nuestra imagen y la convertimos a escala de grises. Esto simplifica el proceso al reducir la información de color a una sola banda:
Esta conversión a escala de grises también nos facilita realizar la descomposición SVD, ya que trabajaremos con una matriz más sencilla.
¿Cómo se realiza la descomposición en valores singulares (SVD)?
Utilizamos numpy para calcular la descomposición SVD de la matriz que representa nuestra imagen:
U, S, Vt = np.linalg.svd(imagen_array, full_matrices=False)
Aquí, U y Vt son matrices ortogonales, mientras que S es un vector que contiene los valores singulares. Estos valores singulares están ordenados de mayor a menor, identificando los componentes más significativos de la imagen.
¿Cómo reconstruir la imagen utilizando SVD?
La reconstrucción de la imagen usando una cantidad reducida de valores singulares es clave para la compresión. Utilizamos solo los valores singulares más grandes, ya que representan la mayor parte de la información visual:
k =50# número de valores singulares consideradosS_k = np.diag(S[:k])U_k = U[:,:k]Vt_k = Vt[:k,:]imagen_reconstruida = np.dot(U_k, np.dot(S_k, Vt_k))
Al variar k, podemos observar el efecto que tiene en la calidad de la imagen reconstruida. Cuanto mayor sea k, mejor será la calidad visual pero también mayor el tamaño del archivo.
¿Qué tamaño de archivo y calidad de imagen obtenemos al variar k?
La elección de k afecta directamente al tamaño final de nuestro archivo y la claridad de la imagen reconstruida. Aquí algunas consideraciones:
Con pocos valores singulares: Tendremos un archivo muy comprimido pero con pérdida de detalles. La imagen será menos clara.
Con muchos valores singulares: Conservamos más detalles finos pero el tamaño del archivo es mayor.
La habilidad para elegir el k óptimo depende del propósito: si se necesita reconocimiento más que calidad visual, menos valores serán suficientes.
Concluyendo, la técnica SVD aplicada a imágenes logra un equilibrio único entre compresión y calidad, permitiendo optimizar recursos de almacenamiento sin sacrificar demasiada información visual. Te invitamos a experimentar y determinar cuál es el valor k ideal para tus necesidades específicas. ¡Explora nuevas formas de eficientizar tus proyectos de imágenes!
Aquí estamos tomando la información del canal(banda) L, que es el que es la que tiene la información que nos importa, la información de la imagen en escala de grises.
Algunos se están confundiendo y piensan que solo esta tomando la banda de R de una imagen RGB, pq ese es el ejemplo que da la documentación, pero recuerden que aquí convertimos esa información a una imagen a escala de grises antes, si quieren pueden graficar la banda=1 que es la que da la información de la transparencia y se darán cuenta que solo es un canal sin información importante., lo pueden hacer con el siguiente código.
Espero haya quedado claro y sirva para entender un poco el uso de esta librería.
Excelente explicación
muchas gracias :)
He is Him.
Los valores singulares de la matriz transformada mediante np.lingalg.svd estan ordenados de manera tal que los primeros elementos contienen la mayor informacion (varianza) de la imagen
Podemos reconstruir una imagen a partir de una parte de los vectores y valores singulares. No se necesitan todos los vectores ni valores para reconstruirla.
No teman compañeros, la zebra no ha muerto. Solo fue divididia gracias a la descomposición de matrices, siendo U , la cabeza, D las patas y V las rayas
getdata() Devuelve el contenido de esta imagen como un objeto de secuencia que contiene valores de píxeles. El objeto de secuencia se aplana, de modo que los valores para la línea uno siguen directamente después de los valores de la línea cero, y así sucesivamente.
Tenga en cuenta que el objeto de secuencia devuelto por este método es un tipo de datos PIL interno, que solo admite ciertas operaciones de secuencia. Para convertirlo a una secuencia ordinaria (por ejemplo, para imprimir), use list (im.getdata ()).
.
fuente: https://www.geeksforgeeks.org/python-pil-image-getdata/
La banda son los canales RGB, porque usar el canal red, buena pregunta.
Lamentablemente esto no explica bien que otros valores puedo ingresar a parte de band=0, intente con otros como el 1 o el 2 pero solo arroja errores.
Buenas, alquien me podria definir que es un valor singular? Muchas gracias.
Son los escalares que componen la matriz diagonal D
por qué se colocó el * en vez de el producto interno?
Para limitar la cantidad de valores singulares que usará en la operación.
puedes hacerlo de las 2 formas , en este caso da igual pq estas trabando con vectores U[:,:1] es solo la primera columna de la matriz U, osea, un vector
debería explicar a con detalle lo de la banda
La banda son los canales RGB, porque usar el canal red, buena pregunta.
Te explico, debido a que en las líneas anteriores colocamos convert("LA"). EL "L" convierte la imagen a escala de grises y el "A" muestra la transparencia de la imagen.
Si te pones a jugar con los números de banda, verás que sólo te deja poner 0 y 1. Si pones 0 y lo corres te dará la imagen en escala de grises "L" (Que es independiente de si le colocas un cmap diferente de gray). Si colocas 1, verás que te sale una imagen de un color sólido, esto representa la transparencia en tu imagen, si no tienes partes transparentes o semitransparentes, posiblemente también te salga como un color sólido.
Excelente aplicación gráfica de la Descomposición en Valores Singulares. Sin duda esto emociona. Me ha dejado con la intriga.
# Cargar una imagen en escala de grises
imagen = plt.imread('imagen.png')# Obtener las dimensiones de la imagen
alto, ancho = imagen.shape# Aplicar la descomposición SVD a la imagen
U,S,Vt= np.linalg.svd(imagen)# Definir el número de componentes principales a utilizar
k =100# Reconstruir la imagen utilizando los k componentes principales
imagen_reconstruida =U[:,:k] @ np.diag(S[:k]) @ Vt[:k,:]# Visualizar la imagen original y la imagen reconstruida
plt.subplot(1,2,1)plt.imshow(imagen, cmap='gray')plt.title('Imagen original')plt.axis('off')plt.subplot(1,2,2)plt.imshow(imagen_reconstruida, cmap='gray')plt.title(f'Imagen reconstruida (k={k})')plt.axis('off')plt.tight_layout()plt.show()
Te tardan en cargar mucho las intrucciones?
Si alguno le pasa como ami que las instrucciones le tarda muchisimo en cargar es porque se necesita un poder de computo bastante elevado para trabajar con matrices tan grandes. Estaba en mi netbook que digamos que anda fluido pero tiene 4 gb y un i3 lo que la volvio muy limitada para calcular estas matrices tan grandes
Les recomiendo instalar Google Colaboratory y subir su projecto de Notebook ahi ya que van a usar una Maquina Virtual de Google con 12gb RAM que les va a poder permitir trabajar aunque la PC que usen no se aguante estos codigos que necesitan tanta potencia de computo
La imagen de ejemplo de esta clase la pueden descargar del siguiente link:
Imagen Ejemplo
Recuerda que debes guardarla en con un nombre y ubicación conocidos para poder acceder en el código
Tambien pueden acceder des de la ruta directamente donde la guardaron :D
Para que sirve el parámetro "banda=0" ??
band - Qué banda volver. El valor predeterminado es devolver todas las bandas. Para devolver una sola banda, pase el valor del índice (por ejemplo, 0 para obtener la banda "R" de una imagen "RGB").
.
Te explico, debido a que en las líneas anteriores colocamos convert("LA"). EL "L" convierte la imagen a escala de grises y el "A" muestra la transparencia de la imagen.
Si te pones a jugar con los números de banda, verás que sólo te deja poner 0 y 1. Si pones 0 y lo corres te dará la imagen en escala de grises "L" (Que es independiente de si le colocas un cmap diferente de gray). Si colocas 1, verás que te sale una imagen de un color sólido, esto representa la transparencia en tu imagen, si no tienes partes transparentes o semitransparentes, posiblemente también te salga como un color sólido.
Habria que usar todos los valores singulares , no solamente uno , aunque este tenga la mayor varianza de datos .. Habria que usar los 3456 valores singulares .... ?????
me gustó el efecto que le dió
Sigo teniendo problemas con traer la imagen al código, saben que más puedo probar a parte de lo que hace el profesor? :)
Revisa que estes ubicandote dentro de la carpeta correcta, no sé en qué estés trabajando. También es muy importante la cuestión de las diagonales, tenemos dos tipos "/" y "\". Si utilizas el "\" y estás en windows, utiliza el doble, si utilizas "/", puedes colocar una r, antes de comenzar el path: r"./algo.png".
Espero haber entendido bien y que te ayude.
es genial ver como pasamos de una imagen a una matriz, bueno a varias matrices que al final del dia terminan siendo una misma.
excelente