enero 27, 2021 10:00 am

Jesús

Las operaciones morfológicas son simples transformaciones que llevamos a cabo sobre los objetos en una imagen con base a su forma, de ahí el nombre.

Las dos transformaciones básicas son erosión y dilación, las cuales disminuyen o expanden, respectivamente, el contorno o, mejor dicho, los límites de un objeto.

Luego, nos topamos con otras operaciones suplementarias como apertura, clausura, gradiente, top hat y black hat, siendo muchas se estas el resultado de aplicar erosiones y dilaciones en difente orden.

Una operación morfológica requiere dos elementos básicos:

  1. 1
    Una imagen de entrada sobre la cual actuar, típicamente binaria.
  2. 2
    Un kernel o elemento estructurante que define la naturaleza de la transformación en sí.

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

  • Qué son las transformaciones morfológicas.
  • Cuáles transformaciones morfológicas están disponibles en OpenCV.
  • Cómo aplicar diversas transformaciones morfológicas en OpenCV.
  • Cómo crear kernels a la medida en OpenCV.

Creación del Entorno de Desarrollo con virtualenv

Veamos la estructura del proyecto de hoy:

datasmarts
└── morph.py

En el archivo datasmarts/morph.py demostraremos las múltiples transformaciones morfológicas que OpenCV nos ofrece.

Para crear el entorno de desarrollo que nos corresponde, ejecutamos los siguientes comandos:

Luego, instalamos las dependencias que se listan a continuación:

¿Cómo llevamos a cabo tal instalación? Pues, con pip, así:

pip install -r requirements.txt

Con esto ya hemos finalizado los preparativos. Empecemos a implementar en la próxima sección.

Implementación del Script de Transformaciones Morfológicas con OpenCV

Abre el archivo datasmarts/morph.py e inserta las siguientes líneas, las cuales importan los módulos y funcionalidades que usaremos en nuestro programa:

Cargamos la imagen de demostración, en escala de grises, y aplicaremos un NOT a nivel de bits para asegurarnos de que los píxeles correspondientes al objeto (un caballo) sean blancos y el fondo negro:

Luego, crearemos un kernel, que no es más que una matriz de 5x5 de sólo unos, que usaremos para aplicar las diferentes transformaciones morfológicas que veremos en breve. Puedes imaginar que un kernel es una especie de brocha que pasamos de izquierda a derecha, y de arriba a abajo sobre la imagen, aplicando el efecto o transformación deseada:

La primera operación que veremos es erosión, que actúa de manera similar a la erosión en la vida real, reduciendo los bordes de los objetos en primer plano. La erosión actúa de la siguiente forma: Un píxel en la imagen original seguirá siendo 1 (recuerda que la imagen tiene que ser binaria, por ende, todos los píxeles son 1 o 0) si todos los píxeles bajo el kérnel también son 1; si no, el nuevo valor de dicho píxel será 0.

En consecuencia, un kernel más grande tenderá a erosionar más que un kernel pequeño. Abajo estamos aplicando erosión en dos iteraciones:

La siguiente transformación es dilación, la cual también actúa como la dilación en la vida real, expandiendo los límites de un objeto. La dilación actúa así: Un píxel tendrá valor 1 si al menos un píxel bajo el kernel también es 1:

La apertura es el resultado de una erosión seguida de una dilación. Es útil para remover ruido en las imágenes:

En contraste, la clausura es una dilación seguida de una erosión. Es buena para cerrar pequeños agujeros o puntos negros en los objetos en primer plano:

El gradiente morfológico es la diferencia entre la dilación y la erosión de una imagen, lo que resulta en el contorno de los objetos en primer plano:

El top hat (no tengo idea de dónde viene el nombre) es la diferencia entre la imagen original  y la apertura:

El black hat (tampoco sé de dónde viene el nombre) es la diferencia entre la clausura y la imagen original:

Por último, como te habrás dado cuenta, usamos dos elementos estructurantes (kernels) creados a mano, uno de 5x5 y otro de 9x9. Sin embargo, en ocasiones podemos necesitar kernels con formas específicas, como cruces, rectángulos o elipses. Mediante OpenCV podemos crear dichos kernels:

Ejecución del Script de Transformaciones Morfológicas con OpenCV

Pongamos a prueba el programa con este comando:

python datasmarts/morph.py

En principio, veremos el resultado de erosionar el caballo en la imagen de prueba:

Erosión

Erosión

Como es natural, el caballo ocupa menos área puesto que su contorno ha sido exitosamente erosionado. Lo siguiente que veremos es el caso contrario, dilación:

Dilación

Dilación

El caballo en la derecha es más grueso que el original, ya que su contorno se dilató. Luego veremos la apertura:

Apertura

Apertura

A pesar de que se trata de una erosión seguida de una dilación, no volvemos a la imagen original del caballo, pero sí a una forma cercana. Veamos seguidamente el resultado de una clausura:

Clausura

Clausura

Como discutimos arriba, una clausura es una dilación seguida de una erosión. Nuevamente, el resultado no es igual al original, pero se acerca. Ahora, detallemos el gradiente:

Gradiente morfológico

Gradiente morfológico

Como el gradiente es la diferencia entre la dilación y la erosión de una imagen, tiene sentido que el resultado sea un contorno o perímetro, ya que el efecto de la primera operación es expandir el caballo, mientras que la segunda lo achica. Veamos ahora el top hat:

Top hat

Top hat

El top hat es la diferencia entre la imagen original y la apertura, lo que nos da una idea de qué partes añadidas por la segunda operación no tienen correspondencia en la imagen original. ¿Qué hay del black hat?

Black hat

Black hat

El black hat es la diferencia entre la clausura y la imagen original. Nuevamente, el resultado son unos trazos o segmentos añadidos por la primera operación, que no corresponden al objeto original.

Por último, en la consola veremos el resultado de crear kernels con distintas formas geométricas:

Kernels

Kernels

Brutal, ¿no?

Resumen

Hoy aprendimos que las transformaciones morfológicas son una serie de operaciones simples que trabajan sobre la forma de los objetos en una imagen (típicamente binarias).

Estas transformaciones nos sirven para reducir ruido y, en líneas generales, limipiar y preprocesar una foto digital antes de aplicar algún algoritmo más complejo. 

También descubrimos que las dos transformaciones morfológicas principales son la erosión y la dilación, las cuales actúan de la misma manera que su contraparte real, achicando o expandiendo los límites del objeto, respectivamente.

Asimismo, aprendimos que dependiendo del orden en el que efectuemos una erosión o una dilación, obtendremos resultados diversos, y que tales operaciones también tienen nombre: apertura, clausura, gradiente, top hat y black hat.

Finalmente, vimos que OpenCV nos puede asistir en la creación de elementos estructurantes, también conocidos como kernels, con formas específicas, los cuales pueden alterar dramáticamente los resultados de las transformaciones morfológicas estudiadas.

Mi reto para ti es que repitas las distintas transformaciones estudiadas el día de hoy, pero con kernels elípticos, rectangulares y en forma de cruz. ¿Cómo se ven afectados los resultados? Compárteme tus impresiones en los comentarios.

¡Hasta luego! ¡Un abrazo!

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.