Comparación visual de etiquetado#
Un primer paso importante al comparar algoritmos de segmentación es visualizar los resultados de los algoritmos individuales y mostrar las diferencias entre ellos.
import numpy as np
from skimage.io import imread
from pyclesperanto_prototype import imshow
import matplotlib.pyplot as plt
import pandas as pd
Simplemente visualizando las imágenes, podemos ver que ningún par de los cuatro algoritmos comparados produce la misma imagen de etiquetas.
filenames = [
"blobs_labels_imagej.tif",
"blobs_labels_skimage.tif",
"blobs_labels_clesperanto_python.tif",
"blobs_labels_clesperanto_imagej.tif"
]
for filename in filenames:
print(filename)
label_image = imread(filename)
imshow(label_image, labels=True)
blobs_labels_imagej.tif
blobs_labels_skimage.tif
blobs_labels_clesperanto_python.tif
blobs_labels_clesperanto_imagej.tif
Como los objetos correspondientes tienen diferentes colores en esta visualización, podemos concluir que al menos las etiquetas de los objetos son diferentes. Aún no podemos concluir si el método de umbralización de Otsu proporciona resultados diferentes en las implementaciones dadas.
Imágenes de diferencia#
Para ver la superposición entre las diferentes imágenes, produciremos imágenes binarias a partir de las imágenes de etiquetas y visualizaremos la diferencia entre estas imágenes binarias.
Primero comparamos el resultado de ImageJ y el resultado de scikit-image para demostrar el procedimiento.
binary_blobs_imagej = imread(filenames[0]) > 0
binary_blobs_skimage = imread(filenames[1]) > 0
imshow(binary_blobs_imagej)
imshow(binary_blobs_skimage)
Al observar estas dos imágenes con cuidado, ya se puede ver que los objetos son un poco más grandes en la segunda imagen.
Para producir la imagen de diferencia, usaremos el método logical_xor de numpy. Establecerá todos los píxeles en la imagen de diferencia a 1, donde cualquiera de las dos imágenes binarias de entrada sea 1, pero no ambas. Se llama el operador OR exclusivo.
difference = np.logical_xor(binary_blobs_imagej, binary_blobs_skimage)
fig, axs = plt.subplots(figsize=(10,10))
axs.imshow(difference)
<matplotlib.image.AxesImage at 0x24619eb5130>
A partir de esta imagen binaria, podemos contar el número de píxeles que son diferentes entre estos dos enfoques:
np.sum(difference)
830
Una matriz de conteos de píxeles diferentes#
Ahora programaremos dos bucles for que iteran sobre pares de imágenes de etiquetas y las comparan usando el mismo enfoque. El resultado será una matriz de 4x4 con el número de píxeles que son diferentes al comparar las implementaciones de algoritmos correspondientes.
matrix = {"Algorithms": filenames}
for filename_A in filenames:
image_A = imread(filename_A)
measurements = []
for filename_B in filenames:
image_B = imread(filename_B)
difference = np.logical_xor(image_A, image_B)
number_of_different_pixels = np.sum(difference)
measurements.append(number_of_different_pixels)
matrix[filename_A] = measurements
pd.DataFrame(matrix)
| Algorithms | blobs_labels_imagej.tif | blobs_labels_skimage.tif | blobs_labels_clesperanto_python.tif | blobs_labels_clesperanto_imagej.tif | |
|---|---|---|---|---|---|
| 0 | blobs_labels_imagej.tif | 0 | 830 | 830 | 830 |
| 1 | blobs_labels_skimage.tif | 830 | 0 | 0 | 0 |
| 2 | blobs_labels_clesperanto_python.tif | 830 | 0 | 0 | 0 |
| 3 | blobs_labels_clesperanto_imagej.tif | 830 | 0 | 0 | 0 |
De esta matriz, podemos concluir que solo el resultado de ImageJ es diferente de las otras tres implementaciones.
Ejercicio#
También deberíamos confirmar rápidamente eso mirando otra imagen de diferencia, por ejemplo, entre la implementación de clesperanto en Jython y scikit-image en Python. Visualiza ambas imágenes binarias y la imagen de diferencia entre estas dos. También cuenta el número de píxeles que son diferentes entre estas dos imágenes.