Postprocesamiento de imágenes binarias utilizando operaciones morfológicas#

Las operaciones morfológicas transforman imágenes basándose en la forma; típicamente nos referimos a imágenes binarias en este contexto.

import numpy as np
from skimage.io import imread
import matplotlib.pyplot as plt
from skimage import morphology
from skimage import filters

Kernels, huellas y elementos estructurales#

Si trabajamos con scikit-image, muchos filtros morfológicos tienen un parámetro footprint. Esta huella es el kernel del filtro, y en la literatura también encontrarás el término elemento estructural para esto.

# crea un disco de 1 con radio = 3
disk = morphology.disk(3) 
disk
array([[0, 0, 0, 1, 0, 0, 0],
       [0, 1, 1, 1, 1, 1, 0],
       [0, 1, 1, 1, 1, 1, 0],
       [1, 1, 1, 1, 1, 1, 1],
       [0, 1, 1, 1, 1, 1, 0],
       [0, 1, 1, 1, 1, 1, 0],
       [0, 0, 0, 1, 0, 0, 0]], dtype=uint8)
plt.imshow(disk, cmap='gray')
<matplotlib.image.AxesImage at 0x225b0c88340>
../_images/2ce56700144d6f8989abd8050950954b7bd4789e6cd2a1099608849e30beabe7.png
# crea un cuadrado con ancho y alto = 3
square = morphology.square(3) 
square
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]], dtype=uint8)

Morfología binaria#

Para demostrar el filtrado morfológico de imágenes binarias, usaremos nuevamente la imagen pequeña de núcleos.

image_nuclei = imread('../../data/mitosis_mod.tif').astype(float)
image_binary = image_nuclei > filters.threshold_otsu(image_nuclei)

plt.imshow(image_binary, cmap='gray')
<matplotlib.image.AxesImage at 0x225b0d05490>
../_images/56ab869e45d7333845132a88738966b807dd35f12510c333bbe203c03660b693.png

Erosión y Dilatación#

Para hacer que las islas blancas en el océano negro sean más pequeñas, necesitamos erosionar sus costas.

eroded = morphology.binary_erosion(image_binary, disk)

plt.imshow(eroded, cmap='gray')
<matplotlib.image.AxesImage at 0x225b0d80dc0>
../_images/d838c1304d54d3eaa1ff7f21cf123079d931e4f7dccf866c0345ea5f62330954.png

Si dilatamos la imagen después, obtenemos islas blancas que se ven más suaves que en la imagen binaria original.

eroded_dilated = morphology.binary_dilation(eroded, disk)

plt.imshow(eroded_dilated, cmap='gray')
<matplotlib.image.AxesImage at 0x225b107f730>
../_images/7c55ef4ae2d61ff4f6963cd2545398174849e8f30a917c3925d3720cdfa4693b.png

Llamar a la erosión y dilatación subsecuentemente es tan común que hay una función extra que hace exactamente eso. Como el espacio entre las islas se abre, la operación se llama apertura.

opened = morphology.binary_opening(image_binary, disk)

plt.imshow(opened, cmap='gray')
<matplotlib.image.AxesImage at 0x225b10f9b20>
../_images/7c55ef4ae2d61ff4f6963cd2545398174849e8f30a917c3925d3720cdfa4693b.png

Ejercicio 1#

También existe una operación de cierre. Aplícala a la imagen binaria.

Ejercicio 2#

Busca en la documentación de scikit-image los filtros de mínimo y máximo. Aplica el filtro de mínimo a la imagen binaria y el filtro de máximo al resultado después. Compáralo con las imágenes mostradas arriba.