¿Cómo procesar imágenes en programación utilizando matrices?
Procesar imágenes en programación no es solo una habilidad técnica, sino una puerta de entrada al entendimiento profundo del reconocimiento de patrones y la compresión de datos. Al analizar una imagen, en realidad, lo que estamos observando son matrices de datos que representan los colores y la intensidad de cada píxel. Exploraremos cómo emplear herramientas como Python y sus bibliotecas para manipular imágenes de manera efectiva.
¿Qué bibliotecas se necesitan?
Para trabajar con imágenes en Python, utilizaremos las siguientes bibliotecas:
PIL (Pillow): Permite la apertura, manipulación y guardado de diferentes formatos de imagen.
Numpy: Facilita operaciones matemáticas y es extremadamente útil para convertir imágenes en matrices y viceversa.
Matplotlib: Nos ayuda a visualizar imágenes matrices al igual que sus alteraciones.
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
¿Cómo abrir y mostrar una imagen?
Para abrir y mostrar una imagen, primero la cargamos usando PIL y luego la visualizamos usando Matplotlib. Asegúrate de especificar la ruta correcta a tu imagen y las barras dobles si trabajas en Windows.
La conversión a escala de grises es un paso crucial en preprocesamiento. Para hacerlo, utilizamos la función convert('L') de Pillow, que transforma la imagen conservando solo la luminancia.
Convertimos nuestra imagen en escala de grises a una matriz utilizando Numpy. Esto nos permitirá analizar y modificar directamente los valores de los píxeles.
matriz_imagen = np.array(imagen_gris)print(matriz_imagen.shape)# Visualizar la forma de la matriz
¿Cómo aplicar operaciones sobre matrices?
Trabajar directamente con los datos nos permite realizar operaciones matemáticas avanzadas. Por ejemplo, dividir los valores de la matriz para normalizar los datos entre 0 y 1, lo que es común en Machine Learning.
Optimización: Al tener todos los valores entre 0 y 1, se facilitan cálculos y converge más rápido en procesos de aprendizaje de máquina.
Comparabilidad: Nos permite mantener relaciones proporcionales y consistentes entre distintos datos.
¿Cuál es el impacto de alterar la matriz?
Modificando directamente la matriz, podemos cambiar cómo se presenta una imagen. Por ejemplo, dividir todos los valores por 10 alterará la percepción de brillo en la imagen. Esto es muy útil para experimentar y entender cómo las transformaciones afectan la imagen final.
Este enfoque nos permite un amplio control en el preprocesamiento de imágenes y es un paso vital hacia técnicas más avanzadas como la reducción dimensional y la compresión de imágenes. Continúa explorando este mundo fascinante y conviértete en un experto en procesamiento de imágenes en Python. Siempre hay nuevas técnicas y herramientas emergentes que enriquecen el panorama de la ciencia de datos y la inteligencia artificial cada día.
Al minuto 6:55 aprox., afirma que al haber dividido entre 10 la matriz 'imagen_mat' cambiamos los colores de la imagen. Eso ocurre porque no le pasamos el parámetro cmap='gray'.
Hice el experimento y si no le pasamos el parámetro cmap='gray' la primera vez que reconstruimos la imagen desde 'matriz_mat', y me muestra exactamente la misma imagen en ambas situaciones. Concluyo de eso que lo que afirma es falso, y que los colores no cambian, al menos en el contexto en el que vimos.
Soy relativamente nuevo en el tema, así que no sabría dar una explicación a esto. Lo que conjeturo es que la imagen se ve así, sin el parámetro cmap='gray', por el filtro 'band=0' que pusimos algunas líneas de código antes, cuando definimos la variable 'imagen_mat'. Lo que leí al respecto es que el parámetro band filtra la banda de color RGB (entonces '0' para R).
¿Alguien sabría explicar qué está pasando en realidad?
plt.imshow(imagen_mat,cmap ='gray')
Efectivamente si no pones el "cmap= 'gray'" vas a ver la misma imagen (rojo azul) pero esto es pq no le has indicado a Python que es una imagen en escala de grises.
y para aclarar tu duda, no la imagen no se ve así por lo que se hizo el band=0, solo se ve así pq no le has indicado a Python que quieres ver una imagen en escala de grises.
Igual voy a explicar un poco lo que hacen esas funciones que estas nombrando.
imagen_gr = imagen.convert('LA')
Convierte la imagen RGB a escala de grises, pero entrega una imagen con 2 canales(o bandas) L y A:
L tiene la información de la imagen en escala de grises.
A tiene la información de transparencia de la imagen, como estamos trabajando con una imagen JPG todos los valores en esta matriz son 255.
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.
Espero haya quedado claro.
Para ver los cambios, en la intensidad de cada pixel en escala de grises es necesario hacer lo siguiente:
Cuando leemos una imagen usando la biblioteca PIL obtenemos la instancia de un objeto de la clase Image. Este objeto viene con unos métodos asociados que nos permiten la manipulación de la imagen. En este caso usamos el método convert que nos permite transformar una imagen de un modo a otro, estos modos son RGB, RGBA, CMYk, etc. (aquí dejo documentación sobre los modos disponibles para esta función). Aquí se usó el modo 'LA' que da como resultado una imagen con 2 canales, uno representando la escala de grises y otro representando el canal de transparencia. Ambos canales están representados con 8 bits, lo cual quiere decir que sus valores pueden ir entre 0 y 255.
Esta transformación fue necesaria ya que aunque la imagen que vemos desde un principio está en escala de grises, en realidad al ser leída desde un archivo JPG tiene los 3 canales RGB. Esto se puede comprobar con el método getbands().
Después de la transformación vemos que esta cantidad de canales ha cambiado. Los tres canales (RGB) se han mapeado a uno solo (L) representando los diferentes tonos de grises en la imagen. El canal de transparencia no es últi al haber obtenido la imagen desde un archivo JPG.
Otro método que usamos fue getdata. Este método nos entrega un objeto que contiene la secuencia de valores que componen la imagen. Cuando no se especifica un canal (band) el método devuelve los valores de todos los canales de la imagen. Por ejemplo, para la imagen original cada elemento de la secuencia tendrá una tupla con 3 valores, los 3 valores de cada canal. En total habrá 12763008 valores dado que la imagen tiene un tamaño de 3693x3456.
Algo importante es que esta secuencia de valores tiene un tipo de dato definido dentro de la biblioteca PIL, por lo cual para manipularlo de forma convencional es necesario transformarlo a una lista de python usando el método list().
El resultado muestra que el canal de transparencia siempre tiene un valor de 255 (por haber sido leído desde JPG). Esto se pudo haber evitado si hubiéramos usado sólo el modo 'L'. Finalmente hay que aclarar que en el código se usa el parámetro band=0 justamente para obtener sólo los valores del canal de grises.
Imágenes como matrices
Podemos ver a las imágenes como un conjunto de matrices que contienen los valores de los pixeles de una imagen (valores de RGB) donde las bandas se refieren a cada una de estas matrices
Normalizar es uno de los pasos más importantes al trabajar con datos en ML
Maravillosa clase, necesitaba un ejemplo así para tener más claro el uso de matrices 😎
Hola buenas, que es lo que significa band = 0 en el codigo?
Muchas gracias
Tengo la misma duda! al buscar en la documentación de numpy no encontré :(
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").
En caso de que hayan guardado la imagen en otra sub carpeta, no olviden poner los dos puntos al inicio:
No termino de entender porque le pone estilo clásico, en que afecta??
Por lo que entiendo que dice la documentación es para usar los valores por defecto que tiene la libreria matplotlib en la version 1.X en lugar de los que usa en la 2.
Si no lo ejecutas notarás que los marcos de las imágenes del .imshow de pyplot será blanca y no gris. Otra diferencia que note es que al no especificar un cmap y que corra el por defecto, la escala será la de 'viridis' y no la roja/azul que creo que se llama 'jet'. En la documentación están estos cmaps y sus nombres.
Por clases como esta es que prefiero la educación virtual
Excelente!
plt.imshow (imagen_mat, cmap="brg")
plt.show()
**Si juegan con los colores en -cmap- les salen diferentes variables visuales interesantes, un ejemplo: **
Muy buena clase!
Entiendo lo que quiso transmitir . Sin embargo eso de la escala de grises nos por que no hizo cambiar la imagen . Supongo que debo revisar la documentación de la librería matplotlib .
Tengo entendido que al momento de procesar imágenes para ML un paso importante es volver a escala de grises, así obtenemos la imagen con valores entre 0 y 255 pero aun podemos trabajar con la relación entre los pixeles que es lo que realmente nos interesa :)
Al dividir los valores de la imagen, se ve un cambio en la escala de los colores, pero si se hace leyendo en escala de grises, se obtiene la imagen original en escala de grises, eso quiere decir que lee la relación entre los pixeles, no es literal en la lectura de cada pixel.
La técnica que permite "tirar" la mayoría de los números de una matriz sin que la imagen se vea borrosa o pierda detalles importantes es la normalización y la reducción de dimensiones. Al normalizar los valores de la matriz entre 0 y 1, se conservan las relaciones entre los píxeles, lo que permite mantener la calidad de la imagen. Además, técnicas como PCA (Análisis de Componentes Principales) ayudan a identificar y retener las características más relevantes de la imagen, eliminando datos redundantes.
Me encanta esta clase, empieza a tomar sentido la relación de las representaciones matriciales y su aplicación.
A qué hace referencia el parámetro size[1] y size[2] ?
Equivalente a lo que menciona Wilson, representan la dimensión de la imagen en pixeles