Optimiser les algorithmes de segmentation#
Le plugin Napari napari-workflow-optimizer permet d’optimiser les flux de travail de segmentation d’images de manière pratique.
from napari_workflow_optimizer import JaccardLabelImageOptimizer, Workflow
from skimage.io import imread
import pyclesperanto_prototype as cle
import matplotlib.pyplot as plt
Pour utiliser l’optimiseur, nous devons définir notre flux de travail en utilisant un objet Workflow. Il fonctionne comme un dictionnaire avec des noms d’images comme mots-clés et une liste d’opérations et de paramètres comme valeurs. L’infrastructure sous-jacente est basée sur les graphes dask.
w = Workflow()
# define background subtraction
w.set("blurred", cle.gaussian_blur, "input", sigma_x=5, sigma_y=5)
# define segmentation
w.set("binarized", cle.threshold_otsu, "blurred")
w.set("labeled", cle.label, "binarized")
Ces flux de travail peuvent être explorés. Par exemple, nous pouvons lire quels paramètres d’image sont nécessaires pour commencer.
w.roots()
['input']
Nous pouvons également déterminer quelles sont les images résultantes du flux de travail.
w.leafs()
['labeled']
Après avoir défini les entrées, nous pouvons demander au flux de travail de calculer les résultats.
w.set("input", imread("../../data/blobs.tif"))
result = w.get("labeled")
cle.imshow(result, labels=True)
Pour l’optimisation d’un tel flux de travail, nous avons besoin d’une image d’annotation de référence. Une annotation clairsemée de quelques objets suffit pour cela.
ground_truth = imread("../../data/blobs_sparse_labels.tif")
cle.imshow(ground_truth, labels=True)
Le JaccardLabelImageOptimizer consomme un flux de travail et peut optimiser les paramètres par rapport à une référence clairsemée. Sa fonction optimize renvoie un ensemble de paramètres qui correspond à tous les paramètres numériques du flux de travail.
jlio = JaccardLabelImageOptimizer(w)
best_param = jlio.optimize("labeled", ground_truth, maxiter=20)
best_param
array([4.80023582e+00, 4.44562637e+00, 3.84861161e-04])
Nous pouvons ensuite utiliser l’optimiseur pour définir ces paramètres dans le flux de travail et ensuite lire où dans le flux de travail les paramètres ont été définis.
jlio.set_numeric_parameters(best_param)
# before printing the workflow, we quickly remove the input image
w.remove('input')
print(w)
Workflow:
blurred <- (<function gaussian_blur at 0x0000023723085A60>, 'input', None, 4.8002358210977345, 4.445626372447739, 0.00038486116050511713)
binarized <- (<function threshold_otsu at 0x00000237232EADC0>, 'blurred')
labeled <- (<function connected_components_labeling_box at 0x000002372316AB80>, 'binarized')
Après avoir défini à nouveau l’entrée, nous pouvons également appliquer le flux de travail à l’image et inspecter visuellement le résultat.
w.set("input", imread("../../data/blobs.tif"))
cle.imshow(w.get("labeled"), labels=True)
Autres aperçus de l’optimisation#
Le JaccardLabelImageOptimizer permet également de jeter un coup d’œil au processus d’optimisation appliqué précédemment.
attempt, quality = jlio.get_plot()
plt.plot(attempt, quality)
[<matplotlib.lines.Line2D at 0x23735c22c70>]