Analyse de Bland-Altman pour comparer les algorithmes de segmentation#
Supposons que nous ayons utilisé un algorithme de segmentation pendant de nombreuses années et que nous envisageons maintenant de le remplacer par une version plus récente et plus rapide. Nous devons nous assurer que nous pouvons comparer les résultats entre ces deux versions. Comme les algorithmes de segmentation ne marquent généralement pas les objets dans le même ordre et que le nombre d’objets peut même différer, nous ne pouvons pas facilement comparer les objets par paires. Il est recommandé de résumer les objets segmentés par image, puis de comparer les résultats produits sur des dossiers d’images.
Dans ce notebook, nous allons comparer les statistiques dérivées des résultats de segmentation produits par deux algorithmes sur un dossier d’images.
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
Algorithmes de segmentation à comparer#
Ici, nous écrivons les deux algorithmes de segmentation sous forme de fonctions Python et les testons sur une image.
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
|
Mesures quantitatives#
Plus tard, nous voulons comparer les mesures. Ainsi, nous écrivons une fonction Python qui détermine ces mesures. Dans cet exemple, nous allons calculer la surface moyenne des noyaux segmentés.
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
Collecte des mesures à partir de dossiers#
Nous appliquons maintenant ces deux algorithmes et les mesures dans un dossier d’images.
def compare_measurements_from_algorithms(algorithm_1, algorithm_2, folder, metric):
measurements = {
metric + '_1':[],
metric + '_2':[]
}
# Itérer sur tous les fichiers dans le dossier
for filename in os.listdir(folder):
file_path = os.path.join(folder, filename)
# Vérifier si l'élément actuel est un fichier
if os.path.isfile(file_path) and filename.endswith(".tif"):
# charger l'image
image = imread(file_path)
# la segmenter en utilisant les deux algorithmes
labels_1 = algorithm_1(image)
labels_2 = algorithm_2(image)
# déterminer la surface moyenne et la stocker
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 |
Graphiques de Bland-Altman#
Nous utilisons maintenant le graphique de Bland-Altman pour visualiser les différences.
bland_altman_plot(measurements['area_1'], measurements['area_2'], 'area')
Dans le cas présenté ci-dessus, la différence moyenne de la mesure de surface est d’environ -100, ce qui signifie que le premier algorithme produit en moyenne des mesures de surface plus petites que le second.
À des fins de démonstration, nous allons maintenant comparer le même algorithme dans une variante CPU et 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')
Dans ce cas, nous voyons que la différence moyenne est d’environ 0. De plus, l’intervalle de confiance est beaucoup plus petit que celui comparé précédemment.
Exercice#
Comparez également le deuxième algorithme de segmentation avec sa variante GPU.
Exercice#
Comparez les mesures d’intensité moyenne de deux algorithmes où la surface semble assez différente. Pouvez-vous prédire à quoi ressemblera le graphique de Bland-Altman ?