5.15. Operaciones morfológicas

Las operaciones morfológicas trabajan sobre imágenes binarias – las máscaras que salen de la umbralización y la detección de bordes. Cada operación recorre el mismo tipo de vecindad deslizante que usan los filtros de suavizado, pero la pregunta que plantea en cada posición es de sí o no: ¿están activados todos los píxeles de la vecindad?, ¿está activado algún píxel de la vecindad?, ¿qué aspecto tiene el patrón de activados/desactivados? Las respuestas hacen crecer las regiones, las encogen y recortan sus límites de formas que un filtro de promediado no puede.

La morfología es lo que viene entre una máscara binaria inicial – la salida de la umbralización, la detección de bordes o algún otro clasificador – y la máscara binaria limpia que el resto de la canalización puede usar. Una salida de umbral en bruto suele tener píxeles de ruido aislados repartidos por áreas de primer plano verdadero, pequeños agujeros perforados en regiones que de otro modo serían sólidas, y límites dentados allí donde el umbral cortó cerca del borde de un objeto. La morfología elimina esos defectos.

5.15.1. Las cuatro operaciones clásicas

Dos operaciones primitivas, y dos composiciones de ellas, conforman el conjunto de herramientas morfológicas:

dilate() hace crecer cada región de primer plano. La regla es: todo píxel que tenga al menos un vecino de primer plano en su ventana (2 * size + 1) se convierte en primer plano. El efecto visible es que las regiones de primer plano se agrandan en size píxeles en cada dirección, y los agujeros en su interior se encogen (o desaparecen) en la misma cantidad.

erode() hace lo inverso. Todo píxel que no tenga todos los vecinos de su ventana en primer plano se convierte en fondo. Las regiones de primer plano se reducen en size píxeles en cada dirección, los píxeles de primer plano aislados (que no tienen vecinos de primer plano) desaparecen por completo, y las pequeñas conexiones entre regiones mayores quedan cortadas.

Una región de entrada binaria en el panel más a la izquierda: un cuadrado sólido con un agujero de un píxel en su centro y tres píxeles de ruido aislados a su alrededor. Cuatro paneles a la derecha muestran el resultado de aplicar dilate, erode, open y close a esa entrada. Dilate hace crecer la región, rellena el agujero y convierte cada píxel de ruido en un bloque; erode encoge la región, agranda el agujero y elimina el ruido; open elimina el ruido reproduciendo exactamente la región y su agujero; close rellena el agujero reproduciendo exactamente el contorno de la región y los píxeles de ruido.

Las cuatro operaciones morfológicas clásicas aplicadas a una región binaria ruidosa. Erode encoge; dilate hace crecer; open es erode seguido de dilate (elimina el ruido); close es dilate seguido de erode (rellena los agujeros).

open() es erode seguido de dilate. La imagen erosionada ha tenido cada píxel de ruido aislado eliminado, pero también se ha encogido en size píxeles en cada dirección. Seguir el erode con un dilate del mismo tamaño restaura las regiones de primer plano genuinas a aproximadamente sus límites originales mientras deja ausente el ruido. La composición es lo que hace de open la operación estándar para «eliminar ruido» en la morfología clásica: los píxeles de primer plano aislados desaparecen, las regiones reales vuelven intactas.

close() es la imagen especular – dilate seguido de erode. El dilate rellena los pequeños agujeros dentro de las regiones de primer plano y conecta las regiones separadas por pequeños huecos; el erode encoge el resultado de vuelta a su límite exterior original mientras deja sólido el interior rellenado. close es la operación estándar para «rellenar huecos pequeños».

binary_mask.open(1)       # remove single-pixel noise
binary_mask.close(2)      # fill small holes and gaps

El parámetro size tiene el mismo significado que en los filtros de brillo: size=1 significa una vecindad de 3 por 3, size=2 significa 5 por 5, y así sucesivamente. Tamaños mayores significan una limpieza más agresiva – y un coste por píxel más largo.

5.15.2. Sombrero de copa y sombrero negro

Vale la pena conocer dos composiciones más porque extraen exactamente las características que open y close eliminan:

top_hat() devuelve la diferencia entre la imagen original y su versión abierta – los píxeles de primer plano que open habría eliminado. Eso es literalmente una máscara de los píxeles de ruido, las pequeñas regiones de primer plano aisladas, las estructuras finas de primer plano que la operación open no pudo preservar. Es útil para extraer características pequeñas de primer plano cuando esas características son lo que le importa a la aplicación, en lugar de eliminarlas.

black_hat() devuelve la diferencia entre la versión cerrada de la imagen y la original – los píxeles de fondo que close habría rellenado. Eso es una máscara de los pequeños agujeros dentro de las regiones de primer plano, los huecos estrechos entre regiones que la operación close habría salvado.

Se recurre a ambos con menos frecuencia que a las cuatro operaciones básicas, pero vale la pena recordar el patrón – cuando una aplicación necesita extraer características pequeñas o finas que la pasada de limpieza estándar elimina, el sombrero de copa y el sombrero negro son la forma natural de recuperarlas.

5.15.3. Modo de umbral

Las cuatro operaciones morfológicas básicas aceptan todas una palabra clave entera threshold que suaviza la prueba de activado/desactivado en cada posición. Sin ella, las operaciones se comportan tal como decían las descripciones anteriores: erode() requiere que todos los vecinos estén activados, dilate() requiere al menos uno. Con threshold establecido, cada operación tolera esa cantidad de vecinos votando en sentido contrario. Para erode, threshold es el número de vecinos de fondo que un píxel puede tener y aun así sobrevivir: threshold=4 conserva cualquier píxel con al menos cuatro de sus ocho vecinos activados (en una ventana de 3 por 3 el píxel central tiene ocho vecinos), de modo que no erosiona tan agresivamente. Para dilate, threshold es el número de vecinos de primer plano que un píxel de fondo debe tener de más antes de activarse: threshold=2 requiere al menos tres vecinos de primer plano en lugar de uno, de modo que crece menos agresivamente.

La forma con umbral es útil para ajustar la agresividad de una pasada morfológica sin cambiar el tamaño de su ventana, lo que también cambiaría la escala de las características sobre las que actúa. La mayoría de las aplicaciones se quedan con el comportamiento predeterminado; la forma con umbral está ahí para los casos en que el valor predeterminado es solo ligeramente excesivo o insuficiente.