Introducción a los datos de imágenes
- 10 minutos
En Computer Vision, normalmente se resuelve uno de los siguientes problemas:
- Clasificación de imágenes es la tarea más sencilla, cuando es necesario clasificar una imagen en una de muchas categorías predefinidas, por ejemplo, distinguir un gato de un perro en una fotografía o reconocer un dígito manuscrito.
- Detección de objetos es una tarea un poco más difícil, en la que necesitamos encontrar objetos conocidos en la imagen y localizarlos, es decir, devolver el rectángulo de límite para cada uno de los objetos reconocidos.
- La segmentación es similar a la detección de objetos, pero en lugar de proporcionar un rectángulo de selección, debemos devolver un mapa de píxeles exacto que delimite cada uno de los objetos reconocidos.
Imagen de CS231n Stanford Course
Imágenes como tensores
Computer Vision funciona con Imágenes. Como probablemente sepa, las imágenes constan de píxeles, por lo que se pueden considerar como una colección rectangular (matriz) de píxeles.
En la primera parte de este módulo, trataremos con el reconocimiento de dígitos manuscritos. Usaremos el conjunto de datos MNIST, que consta de imágenes de escala de grises de dígitos manuscritos, 28 x 28 píxeles. Cada imagen se puede representar como matriz de 28 x 28, y los elementos de esta matriz denotarían la intensidad del píxel correspondiente, ya sea en la escala del intervalo de 0 a 1 (en cuyo caso se usan números de punto flotante) o de 0 a 255 (enteros). Una biblioteca popular de Python denominada numpy suele usarse con tareas de Computer Vision, ya que permite operar con matrices multidimensionales de forma eficaz.
Para tratar las imágenes de color, necesitamos alguna manera de representar colores. En la mayoría de los casos, representamos cada píxel en 3 valores de intensidad, correspondientes a los componentes Rojo (R), Verde (G) y Azul (B). Esta codificación de color se denomina RGB y, por tanto, la imagen de color del tamaño W×H se representará como una matriz de tamaño H×W×3 (a veces el orden de los componentes puede ser diferente, pero la idea es la misma). En la representación de matriz, el alto (número de filas) viene delante del ancho (número de columnas), que es lo contrario a la convención de imagen común de W×H.
Las matrices multidimensionales también se denominan tensores. El uso de tensores para representar imágenes también tiene una ventaja, ya que podemos usar una dimensión adicional para almacenar una secuencia de imágenes. Por ejemplo, para representar un fragmento de vídeo que consta de 200 fotogramas con una dimensión de 800x600 (ancho × alto), podemos usar el tensor de tamaño 200x600x800x3. Recuerde que las dimensiones del tensor usan el orden H×W (fila principal), y no la convención W×H que se suele ver en los editores de imágenes. El orden aquí es marcos × alto (600) × ancho (800) × canales. Este orden se conoce como channels_last y es el valor predeterminado en TensorFlow; otros marcos colocan canales antes del alto y el ancho (channels_first).
import tensorflow as tf
import keras
import matplotlib.pyplot as plt
import numpy as np
# Prints the installed TensorFlow version
print(tf.__version__)
Usaremos el marco Keras para nuestros experimentos. En este módulo, usamos import keras (el estilo de importación independiente Keras 3), que requiere TensorFlow 2.16 o posterior (o una instalación independiente a través de pip install keras>=3.0). Si usa una versión anterior de TensorFlow 2.x, reemplace por import kerasfrom tensorflow import keras.
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# Output: (60000, 28, 28) (60000,)
print(x_train.shape, y_train.shape)
# Output: (10000, 28, 28) (10000,)
print(x_test.shape, y_test.shape)
Visualiza el conjunto de datos de dígitos
Ahora que hemos descargado el conjunto de datos, podemos visualizar algunos de los dígitos:
fig, ax = plt.subplots(1, 7)
for i in range(7):
ax[i].imshow(x_train[i])
ax[i].set_title(y_train[i])
ax[i].axis('off')
# Displays a row of seven handwritten digit images with their labels
Estructura del conjunto de datos
Tenemos un total de 60 000 imágenes de entrenamiento y 10 000 imágenes de prueba, y cada imagen tiene un tamaño de 28×28 píxeles:
print('Training samples:', len(x_train))
print('Test samples:', len(x_test))
print('Tensor size:', x_train[0].shape)
print('First 10 digits are:', y_train[:10])
print('Type of data is ', type(x_train))
# Output:
# Training samples: 60000
# Test samples: 10000
# Tensor size: (28, 28)
# First 10 digits are: [5 0 4 1 9 2 1 3 1 4]
# Type of data is <class 'numpy.ndarray'>
Como puede ver, el tipo de datos es numpy array. Cada intensidad de píxel se representa mediante un valor entero entre 0 y 255:
print('Min intensity value: ', x_train.min())
print('Max intensity value: ', x_train.max())
# Output:
# Min intensity value: 0
# Max intensity value: 255
La razón por la que está entre 0 y 255 es porque cada píxel se representa mediante un entero de 8 bits. En muchos casos, especialmente cuando se trabaja con redes neuronales, es más conveniente escalar todos los valores al intervalo [0, 1] dividiendo por 255. Este proceso se denomina normalización:
x_train = x_train.astype(np.float32) / 255.0
x_test = x_test.astype(np.float32) / 255.0
# Pixel values are now floating point numbers in the range [0, 1]
Ahora tenemos los datos y estamos listos para empezar a entrenar nuestra primera red neuronal.