Umbralización#
La umbralización es una técnica de segmentación de imágenes. Separa una imagen de un solo canal dada (o pila) en dos regiones: Píxeles con intensidad por debajo de un umbral dado, también llamado “fondo” y píxeles con intensidad por encima de un umbral dado, “primer plano”. Típicamente, estos algoritmos resultan en imágenes binarias donde la intensidad de fondo es 0 y la intensidad de primer plano es 1. Al aplicar tales algoritmos en ImageJ, los píxeles de primer plano son 255. En scikit-image, los píxeles de fondo son False y los píxeles de primer plano son True.
Ver también
from skimage.io import imread
from pyclesperanto_prototype import imshow
import pyclesperanto_prototype as cle
from skimage import filters
from skimage.filters import try_all_threshold
from matplotlib import pyplot as plt
import napari_simpleitk_image_processing as nsitk
image = imread("../../data/blobs.tif")
imshow(image)
Segmentación de imágenes por umbralización#
La operación threshold_otsu, también conocida como método de Otsu (Otsu et al., IEEE Transactions on Systems, Man, and Cybernetics, Vol. 9 (1), 1979), proporciona un número - el umbral a aplicar.
threshold = filters.threshold_otsu(image)
Cuando se utilizan métodos como la umbralización en notebooks, se recomienda imprimir el resultado para ver qué devuelve realmente. Aquí, estamos utilizando el método de scikit-image, que devuelve el umbral que se aplica. Imprimir ese umbral puede ser útil más adelante al reproducir el flujo de trabajo, también si otros quieren aplicar el mismo umbral al conjunto de datos en otro software.
threshold
120
Usando arrays de numpy, podemos aplicar el umbral utilizando el operador >=. El resultado será una imagen binaria.
binary_image = image >= threshold
imshow(binary_image)
También podemos determinar en qué tipo se procesa la imagen binaria imprimiendo el mínimo y el máximo de la imagen:
binary_image.max()
True
binary_image.min()
False
Como se mostró anteriormente, matplotlib nos permite dibujar un contorno sobre una imagen visualizada usando imshow mediante el comando contour.
# crear un nuevo gráfico
fig, axes = plt.subplots(1,1)
# añadir dos imágenes
axes.imshow(image, cmap=plt.cm.gray)
axes.contour(binary_image, [0.5], linewidths=1.2, colors='r')
<matplotlib.contour.QuadContourSet at 0x2b57076dc70>
Hay una lista de algoritmos de umbralización disponibles. Es posible aplicarlos todos a tus datos y ver las diferencias:
fig, ax = try_all_threshold(image, figsize=(10, 8), verbose=False)
plt.show()
Umbralización usando pyclesperanto#
Además, otras bibliotecas como pyclesperanto también ofrecen algoritmos de umbralización. La implementación aquí no devuelve el umbral, sino que devuelve directamente la imagen binaria.
binary_image2 = cle.threshold_otsu(image)
imshow(binary_image2)
Aquí también podemos ver que diferentes bibliotecas almacenan imágenes binarias de diferentes maneras. pyclesperanto, por ejemplo, almacena los píxeles positivos en imágenes binarias no como True sino con un 1 en su lugar:
binary_image2.max()
1.0
binary_image2.min()
0.0
Umbralización usando SimpleITK#
SimpleITK también ofrece algoritmos de umbralización que se pueden encontrar en la lista de filtros. Para facilitar la escritura de scripts, aquí usamos napari-simpleitk-image-processing, un plugin de napari programable que ofrece algunas funciones de SimpleITK de una manera más accesible. Podemos programar un pequeño bucle for que pruebe todos los algoritmos de umbralización en SimpleITK y nos muestre los resultados:
threshold_algorithms = [
nsitk.threshold_huang,
nsitk.threshold_intermodes,
nsitk.threshold_isodata,
nsitk.threshold_kittler_illingworth,
nsitk.threshold_li,
nsitk.threshold_maximum_entropy,
nsitk.threshold_moments,
nsitk.threshold_otsu,
nsitk.threshold_renyi_entropy,
nsitk.threshold_shanbhag,
nsitk.threshold_triangle,
nsitk.threshold_yen
]
for algorithm in threshold_algorithms:
# mostrar el nombre del algoritmo encima de la imagen
print(algorithm.__name__)
# binarizar la imagen usando el algoritmo dado
binary_image = algorithm(image)
# mostrar el resultado de la segmentación
imshow(binary_image)
threshold_huang
threshold_intermodes
threshold_isodata
threshold_kittler_illingworth
threshold_li
threshold_maximum_entropy
threshold_moments
threshold_otsu
threshold_renyi_entropy
threshold_shanbhag
threshold_triangle
threshold_yen
Ejercicio#
Segmenta blobs.tif usando el algoritmo de Yen. Usa matplotlib para dibujar un contorno verde de los objetos segmentados alrededor de las regiones en la imagen original.
Segmenta la imagen usando un umbral calculado según esta ecuación:
threshold = mean + 2 * standard_deviation
Visualiza la segmentación resultante con un contorno rojo sobre la imagen original y el contorno verde de arriba.
Alternativamente, coloca ambos resultados de segmentación en napari y compáralos visualmente allí.