Análisis de Bland-Altman para comparar algoritmos de segmentación#
Supongamos que hemos estado utilizando un algoritmo de segmentación durante muchos años y ahora estamos considerando reemplazarlo por una versión más nueva y rápida. Necesitamos asegurarnos de que podemos comparar los resultados entre estos dos. Como los algoritmos de segmentación típicamente no etiquetan los objetos en el mismo orden e incluso el número de objetos puede diferir, no podemos comparar fácilmente los objetos por pares. Se recomienda resumir los objetos segmentados por imagen y luego comparar los resultados producidos en carpetas de imágenes.
En este notebook compararemos estadísticas derivadas de los resultados de segmentación producidos por dos algoritmos en una carpeta de imágenes.
folder = '../../data/BBBC007_batch/'
from skimage.io import imread
from skimage.measure import regionprops
from utils import bland_altman_plot
import napari_segment_blobs_and_things_with_membranes as nsbatwm
import pyclesperanto_prototype as cle
import os
import numpy as np
import pandas as pd
import stackview
Algoritmos de segmentación a comparar#
Aquí escribimos los dos algoritmos de segmentación como funciones de Python y los probamos en una imagen.
test_image = imread(folder + "17P1_POS0013_D_1UL.tif")
stackview.insight(test_image)
|
|
|
def segmentation_1(image):
return nsbatwm.voronoi_otsu_labeling(image)
segmentation_1(test_image)
|
|
nsbatwm made image
|
def segmentation_2(image):
return nsbatwm.gauss_otsu_labeling(image)
test_labels = segmentation_2(test_image)
test_labels
|
|
nsbatwm made image
|
Mediciones cuantitativas#
Más adelante, queremos comparar mediciones. Por lo tanto, escribimos una función de Python que determina estas mediciones. En este ejemplo, calcularemos el área media de los núcleos segmentados.
def mean_metric(image, label_image, metric):
properties = regionprops(label_image, image)
values = [p[metric] for p in properties]
return np.mean(values)
mean_metric(test_image, test_labels, "area")
235.70731707317074
Recopilación de mediciones de carpetas#
Ahora aplicamos estos dos algoritmos y las mediciones en una carpeta de imágenes.
def compare_measurements_from_algorithms(algorithm_1, algorithm_2, folder, metric):
measurements = {
metric + '_1':[],
metric + '_2':[]
}
# Iterar sobre todos los archivos en la carpeta
for filename in os.listdir(folder):
file_path = os.path.join(folder, filename)
# Comprobar si el elemento actual es un archivo
if os.path.isfile(file_path) and filename.endswith(".tif"):
# cargar imagen
image = imread(file_path)
# segmentarla usando ambos algoritmos
labels_1 = algorithm_1(image)
labels_2 = algorithm_2(image)
# determinar el área media y almacenarla
measurements[metric + '_1'].append(mean_metric(image, labels_1, metric))
measurements[metric + '_2'].append(mean_metric(image, labels_2, metric))
return measurements
measurements = compare_measurements_from_algorithms(segmentation_1,
segmentation_2,
folder,
'area')
pd.DataFrame(measurements)
| area_1 | area_2 | |
|---|---|---|
| 0 | 210.086957 | 235.707317 |
| 1 | 206.866667 | 244.973684 |
| 2 | 203.023256 | 268.615385 |
| 3 | 185.103448 | 214.720000 |
| 4 | 184.147059 | 362.956522 |
| 5 | 267.057692 | 730.894737 |
Gráficos de Bland-Altman#
Ahora usamos el gráfico de Bland-Altman para visualizar las diferencias.
bland_altman_plot(measurements['area_1'], measurements['area_2'], 'area')
En el caso mostrado arriba, la diferencia promedio de la medición del área es de aproximadamente -100, lo que significa que el primer algoritmo produce en promedio mediciones de área más pequeñas que el segundo.
Con fines de demostración, ahora compararemos el mismo algoritmo en una variante de CPU y GPU.
def segmentation_1_gpu(image):
return cle.voronoi_otsu_labeling(image)
measurements_cpu_vs_gpu = compare_measurements_from_algorithms(segmentation_1,
segmentation_1_gpu,
folder,
'area')
bland_altman_plot(measurements_cpu_vs_gpu['area_1'], measurements_cpu_vs_gpu['area_2'], 'area')
En este caso, vemos que la diferencia promedio es de aproximadamente 0. Además, el intervalo de confianza es mucho más pequeño que en la comparación anterior.
Ejercicio#
Compare también el segundo algoritmo de segmentación con su variante de GPU.
Ejercicio#
Compare las mediciones de intensidad media de dos algoritmos donde el área parece bastante diferente. ¿Puede predecir cómo se verá el gráfico de Bland-Altman?