Las Redes Convolucionales son ampliamente utilizadas para desarrollar diferentes tipos de aplicaciones de la Visión por Computador, como la clasificación de imágenes, la detección de objetos y la segmentación, entre otras. Sin embargo, la variabilidad en los tamaños de las imágenes de entrada representa un problema fundamental, ya que cuando construimos estas redes sus entradas deben ser de tamaño fijo.
Así que en este artículo veremos en detalle cómo resolver un desafío común en la Visión por Computador: entrenar Redes Convolucionales cuando nuestro set de datos contiene imágenes con diferentes tamaños.
El problema del tamaño de entrada en las Redes Convolucionales
Para entender el problema al que nos enfrentamos cuando tenemos imágenes de tamaño variable, necesitamos recordar algunos elementos básicos del funcionamiento de una Red Convolucional.
Este tipo de Red Neuronal está diseñado específicamente para procesar imágenes. En la capa de entrada presentamos la imagen o las imágenes que queremos procesar y a la salida la red puede generar predicciones para clasificar la imagen, generar una segmentación o detectar un objeto:

Pero, ¿qué ocurre cuando vamos a programar en nuestros computadores esa Red Convolucional?. Si nos enfocamos en la capa de entrada (el primer bloque de la red en la figura anterior), al momento de escribir el código encontramos un parámetro de entrada clave: el tamaño de las imágenes.
Por ejemplo, si usamos la librería Keras, este tamaño lo definimos a través del parámetro «input_shape»:
model = models.Sequential([
layers.Conv2D(filters=32, kernel_size=(3, 3), activation='relu', input_shape=(350, 350, 3))
])
Mientras que en PyTorch definimos el tamaño de entrada usando argumentos como «in_channels» así como el tamaño del tensor de entrada («input_tensor»):
# La capa convolucional define los canales de entrada
conv_layer = nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3)
# El tensor de entrada requiere dimensiones espaciales fijas (Batch, Canales, Alto, Ancho)
input_tensor = torch.randn(1, 3, 350, 350)
output = conv_layer(input_tensor)
Lo importante, más allá del código, es tener claro que el tamaño de entrada tiene un alto y un ancho específicos que no se pueden modificar posteriormente. Esto quiere decir que todas las imágenes que ingresan a una Red Convolucional deben tener obligatoriamente el mismo alto y el mismo ancho (y desde luego el mismo número de canales).
El problema práctico es que muchas veces las imágenes de los sets de datos con los que trabajamos tienen diferentes altos y anchos:

Alternativas de preprocesamiento para imágenes de tamaño variable
Dado que una Red Convolucional es una estructura fija que siempre acepta imágenes del mismo tamaño, existen tres alternativas de preprocesamiento que podemos implementar sobre las imágenes para garantizar que sus dimensiones sean uniformes: el recorte de las imágenes (cropping), el rellenado con ceros (padding) o el redimensionamiento (resizing).
1. El recorte de imágenes (cropping)
La primera alternativa de preprocesamiento se conoce como el recorte o cropping. Esta técnica consiste en recortar las imágenes de manera tal que todas tengan el tamaño de la imagen más pequeña de nuestro set de datos.
Para entender esta estrategia, supongamos que tenemos un set de únicamente cinco imágenes organizadas por tamaños de mayor a menor (obviamente en la práctica se usan muchas más imágenes) como se muestra a continuación:

Vemos que la imagen del extremo derecho es la más pequeña de todas. Así que la idea del cropping es quitar porciones de las imágenes, eliminando los elementos adicionales en los bordes para garantizar que todas se ajusten al tamaño de esta imagen más pequeña.
En este caso, tras aplicar el cropping veríamos que para las primeras cuatro imágenes (las más grandes) se han recortado los bordes externos, manteniendo únicamente la porción central de cada una:

El inconveniente de esta alternativa es que, al realizar el recorte de los bordes (como podemos ver en las cuatro primeras imágenes de la parte de arriba) se pierde una gran cantidad de información esencial contenida en ellas.
2. El rellenado con ceros (padding)
La segunda alternativa es el rellenado con ceros o padding. A diferencia del recorte, este enfoque busca ajustar los tamaños de todas las imágenes al tamaño de la imagen con mayores dimensiones (la imagen más grande de todas en el set de datos según el ejemplo anterior).
¿Cómo procesamos las imágenes más pequeñas para que tengan ese tamaño de la imagen más grande?. Pues simplemente se les agregan ceros en los bordes:

Como vemos en la figura de arriba, al realizar este proceso, la imagen más grande de todas (en la parte superior izquierda) sigue manteniendo su tamaño original, pero todas las demás imágenes han sido el resultado de tomar las versiones originales y agregarles pixeles de color negro (que representan los ceros) en la parte de arriba, abajo y a los lados.
Con esto garantizamos que no perdemos información original de la imagen, pero la desventaja del padding es que estamos agregando información completamente irrelevante. En el caso extremo de la imagen inferior derecha (la más pequeña de todas), la gran cantidad de ceros añadidos alrededor provoca que la información verdaderamente relevante quede aislada solo en una pequeña porción de la imagen final.
3. El redimensionamiento (resizing / reshaping)
La tercera alternativa, y la que resulta más recomendable, es el redimensionamiento o reshaping. La idea detrás de este método no es tomar ni la imagen más grande ni la más pequeña como base, sino encontrar un punto intermedio. Es decir, consiste en calcular un valor promedio de alto y ancho y redimensionar todas las imágenes del set a ese tamaño intermedio unificado:

De esta forma, logramos que todas las imágenes tengan el mismo tamaño sin agregarles ceros excesivos y sin quitarles porciones relevantes.
Sin embargo, una desventaja (como lo vemos en la figura de arriba) es que dependiendo del tamaño original, algunas imágenes pueden verse distorsionadas. Por ejemplo, en las imágenes 1 y 4 de la figura anterior se puede observar que sus proporciones no se mantienen iguales, resultando ligeramente estiradas o achatadas con respecto a las imágenes originales.
El tamaño de la imagen como hiperparámetro del modelo
Pese al riesgo de distorsión, el redimensionamiento es la técnica convencionalmente más usada.
Sin embargo, aquí nos surge una pregunta clave: ¿cómo determinamos exactamente el ancho y el alto que deben tener todas las imágenes para entrenar la Red Convolucional?.
La respuesta inicial es que no podemos saber esto con antelación. Al igual que con todo en el Deep Learning, no existe una regla matemática o fórmula general que nos permita deducir antes de construir la red el tamaño más adecuado para lograr el mejor desempeño posible. Cada problema y cada set de imágenes posee particularidades que impiden aplicar una regla universal a todas las situaciones.
Entonces, una alternativa es tratar el ancho y el alto de estas imágenes como un par de hiperparámetros de nuestro modelo. Un hiperparámetro es una cantidad numérica que nosotros debemos elegir de forma manual y que, dependiendo del valor asignado, impactará directamente el desempeño final del modelo. Así, ciertos valores nos darán un buen desempeño, mientras que otros valores generarán resultados deficientes.
Algunos ejemplos de hiperparámetros, en el caso de las Redes Convolucionales, son el número de capas, el número de filtros o el tamaño de esos filtros en cada capa.
Entonces, lo que podemos hacer es redimensionar nuestras imágenes a diferentes combinaciones candidatas de alto y ancho, que usualmente pueden ser entre tres y cuatro combinaciones distintas:

Y la idea es entonces que, por cada una de estas combinaciones, entrenaremos un modelo y evaluaremos su desempeño. Así, en la figura anterior:
- Entrenamos la primera red con la primera combinación y nos arroja una exactitud promedio del 87%.
- Hacemos lo mismo para la segunda combinación y nos da un 93% de exactitud.
- Repetimos el proceso hasta la última de las combinaciones, donde supongamos obtenemos un 91% de exactitud.
Y para saber cuál es la mejor combinación, simplemente seleccionamos aquella que arrojó la mayor exactitud o el mejor desempeño, que en este ejemplo corresponde a la segunda combinación (con 93% de exactitud).
Cómo determinar los tamaños candidatos para el redimensionamiento
Para escoger estos valores candidatos de altos y anchos con los cuales entrenar los diferentes modelos, la clave está en nuestro propio set de datos. Debemos analizarlo para identificar los patrones de tamaños más comunes. Los pasos sugeridos son leer inicialmente cada una de las imágenes y almacenar individualmente sus valores de alto y ancho para luego construir histogramas que nos permitan identificar estos patrones.
Veamos qué tipos de análisis y qué información podemos extraer de estos histogramas.
Análisis de la relación alto sobre ancho
Un primer enfoque es calcular la relación existente entre el alto y el ancho (dividiendo el alto entre el ancho de cada imagen) y construir el correspondiente histograma:

En este histograma (figura anterior) tendremos en el eje horizontal las diferentes relaciones alto/ancho (valores entre cero y un poco más de uno) y en el eje vertical el porcentaje de las imágenes del set que poseen dicha relación. Así, por ejemplo:
- Aquellas imágenes para las cuales el alto es igual al ancho (imágenes cuadradas) tendrán una relación exactamente igual a 1.
- Lo que se ubica a la izquierda de ese umbral (relaciones menores que 1) corresponde a imágenes que son más anchas que altas.
- Lo que se ubica del lado derecho (relaciones mayores que 1) corresponde a imágenes más altas que anchas.
Analizando las porciones donde se concentra la mayor parte de la distribución, podríamos determinar que, por ejemplo para la figura de arriba, más del 70% de las imágenes de este set de datos tienen proporciones entre 1 y 1.2:

Esto nos indica que las imágenes son mayormente cuadradas o un poco más altas que anchas, lo cual nos da una pista clave para luego elegir los tamaños candidatos .
Análisis del total de pixeles (producto de alto por ancho)
El segundo análisis resulta de calcular el producto del alto por el ancho para determinar el número total de pixeles de cada imagen. En la figura de abajo vemos el histograma correspondiente:

Al construir y analizar el histograma correspondiente (figura anterior), podríamos encontrar que más del 70% de las imágenes de este set particular posee aproximadamente 125.000 pixeles al cuadrado.
Si traducimos esta área a un plano cuadrado, estamos hablando de imágenes de aproximadamente 350 x 350 pixeles. Esto nos entrega otro detalle clave sobre el tamaño promedio de las imágenes en el dataset.
Selección de las mejores combinaciones candidatas
Si ahora combinamos las observaciones de ambos histogramas (la gran cantidad de imágenes con áreas de 125.000 pixeles al cuadrado, aproximadamente) junto con las proporciones que varían desde 1 hasta ligeramente por encima de 1), podemos por ejemplo definir tres combinaciones iniciales para evaluar:

- 350 x 350 pixeles: una primera combinación cuadrada fundamentada en la moda de área del segundo histograma.
- 450 x 350 pixeles: dado que el primer histograma mostró relaciones de tamaño mayores que 1 (imágenes rectangulares), podemos probar un tamaño rectangular con un número de píxeles un poco mayor.
- 300 x 250 píxeles: una tercera alternativa rectangular con un área un poco inferior.
Con estas tres posibles combinaciones ya podemos entrenar diferentes modelos y determinar de forma empírica cuál hiperparámetro resulta más adecuado en términos de las predicciones de la Red Convolucional que estemos entrenando.
Conclusión
Muy bien, en este artículo hemos visto las principales estrategias que sugiero usar cuando queremos entrenar Redes Convolucionales para el caso en el cual las imágenes de nuestro set de datos tienen tamaños (altos y anchos) diversos.
En la práctica, también es importante tener en cuenta que debemos evitar el uso de imágenes con tamaños, altos o anchos, que sean demasiado grandes (generalmente aquellos que sean superiores a los 1200 pixeles). Esto debido a que, entre más grandes sean las imágenes suministradas para entrenar el modelo, más prolongado resultará el tiempo de entrenamiento computacional. Además, en la práctica un mayor tamaño no necesariamente garantizará un mejor desempeño de la red.
Por otra parte, si en lugar de entrenar nuestro modelo de cero lo que hacemos es usar un modelo pre-entrenado (como por ejemplo VGG16, ResNet, Inception o YOLO), debemos tener en cuenta que la mayor parte de estos modelos aceptan tamaños muy inferiores a este umbral de 1200 pixeles, operando usualmente con entradas que oscilan entre los 224 y los 700 pixeles (alto o ancho) aproximadamente.
