abril 15, 2021 10:00 am

Jesús

Como bien sabemos, las imágenes digitales son, en pocas palabras, matrices glorificadas. 

Por consiguiente, muchas de las operaciones básicas que desempeñamos sobre estas, tales como traslaciones, rotaciones, ajustes de tamaño, entre otras, tienen su fundamento en el álgebra.

Afortunadamente, librerías como OpenCV o scikit-learn ofrecen algunas funciones de alto nivel que esconden estos cálculos relativamente complejos, aunque definitivamente incómodos, lo cual se agradece.

No obstante, darnos el tiempo de entender los fundamentos es una inversión que siempre rinde frutos.

El día de hoy, pues, aprenderemos cómo implementar varias de las operaciones básicas mencionadas ut supra utilizando álgebra, y más específicamente, un concepto denominado transformación afín.

Al final de este artículo habrás aprendido:

  • Qué es una transformación afín.
  • Cuáles son las transformaciones afines correspondientes a identidad, reflexión, escalado, rotación y recorte.
  • Cómo construir las matrices de transformaciones afines correspondientes a identidad, reflexión, escalado, rotación y recorte.
  • Cómo aplicar transformaciones afines en scikit-image y scipy

¿Estás listo? ¡Comencemos!

¿Qué son las Transformaciones Afines?

En geometría, una transformación afín (también conocida como afinidad) está compuesta de una transformación lineal seguida de una traslación o desplazamiento.

En español, una transformación afín no es más que una operación que conserva las líneas y el paralelismo, más no las distancias ni los ángulos.

Aplicado a imágenes, lo que esto significa es que conservaremos la figura general de los objetos y elementos representados, más no su ubicación relativa, lo cual está muy bien, ya que es lo que nos permite rotar, trasladar o escalar una foto.

Abajo podemos ver la estructura de la matriz de transformación correspondiente a cada operación:

En las próximas secciones implementaremos estas transformaciones usando las matrices mostradas arriba.

Sigamos adelante.

Creación del Entorno de Desarrollo con virtualenv

Nuestro proyecto se compone principalmente del archivo datasmarts/affine.py, como se aprecia en el diagrama de abajo:

datasmarts
└── affine.py

Para crear y activar el entorno virtual, ejecuta las siguientes instrucciones:

Nuestra solución depende de estas librerías:

Para instalarlas, solo debemos correr este comando:

pip install -r requirements.txt

Eso es todo. Pasemos a la próxima sección.

Transformaciones Afines en scikit-image

Abre el archivo datasmarts/affine.py e inserta estas líneas, las cuales importan los módulos relevantes:

Luego, definimos el menú del programa, el cual únicamente recibe la ruta a la imagen de entrada, a través del parámetro -i/--image:

Después, leemos la imagen y la convertimos en escala de grises:

También aprovechamos para extraer las dimensiones de la foto:

La primera transformación que llevaremos a cabo es una estéril, la cual no surte efecto alguno, conocida como identidad:

En principio, construimos la matriz identidad y la aplicamos mediante la función ndimage.affine_transform(). Repetiremos este patrón para cada transformación.

Ahora llevaremos a cabo una reflexión alrededor del eje X. Para ello, debemos construir una matriz de transformación que resulta del producto interno de otras dos. Fíjate que en NumPy el operador del producto interno de matrices es @:

La siguiente operación es un escalado o redimensionamiento. Para ello, instanciamos la matriz de escalado y la aplicamos sobre la imagen (por un factor de 0.75 en el eje X, y uno de 1.25 en el eje Y):

A continuación rotaremos la imagen 30 grados en sentido antihorario. Nota que se trata de una operación compuesta, ya que primero tenemos que centrar la imagen, luego rotarla, y finalmente revertir el centrado; por este motivo calculamos el producto interno de tres matrices:

Por último, cortaremos la imagen:

Finalizamos nuestro script dibujando todas las transformaciones en un mismo lienzo:

Puedes correr el programa como sigue:

python datasmarts/affine.py -i car.jpeg

El resultado es este:

En la primera imagen tenemos la foto original, luego de convertirla a blanco y negro. Como es de esperar, la transformación identidad no afectó a la imagen original. En las celdas subsiguientes del gráfico, notamos que aplicamos de forma exitosa cada operación, un gran indicativo de que construimos y utilizamos apropiadamente las matrices de transformaciones afines.

Genial, ¿no crees?

Resumen

Hoy aprendimos que una transformación de afinidad es aquella que preserva el paralelismo entre líneas de una imagen, pero no los ángulos ni las distancias, lo cual las convierte en las herramientas perfectas para alterar la perspectiva y disposición de los objetos en las fotos.

Luego, implementamos varias de las operaciones básicas más comunes, como rotación, escalado y reflexión, definiendo la matriz correspondiente, para luego aplicarla mediante la función ndimage.affine_transform() sobre la imagen objetivo.

Afortunadamente contamos con abstracciones tanto en scikit-image y OpenCV que nos ahorran la complejidad de construir estas matrices a mano, pero siempre es bueno conocer los fundamentos teóricos.

¿Por qué no descargas el código y sigues explorando por tu cuenta? Mejor aún, expándelo para llevar a cabo las mismas transformaciones en scikit-image y compara los resultados.

¡Hasta pronto!

Sobre el Autor

Jesús Martínez es el creador de DataSmarts, un lugar para los apasionados por computer vision y machine learning. Cuando no se encuentra bloggeando, jugando con algún algoritmo o trabajando en un proyecto (muy) cool, disfruta escuchar a The Beatles, leer o viajar por carretera.