Étiquetage séquentiel des objets (ré-étiquetage)#

Comme mentionné précédemment, selon le cas d’utilisation, il peut être important d’étiqueter les objets d’une image de manière séquentielle. Il pourrait par exemple arriver qu’un algorithme de post-traitement pour les images étiquetées échoue si nous lui transmettons une image étiquetée avec des étiquettes manquantes. Par conséquent, nous devrions savoir comment ré-étiqueter une image de manière séquentielle.

import numpy as np
from skimage.io import imread
from skimage.segmentation import relabel_sequential
import pyclesperanto_prototype as cle

Notre point de départ est une image étiquetée avec les étiquettes 1-8, où certaines étiquettes ne sont pas présentes :

label_image = imread("../../data/label_map_with_index_gaps.tif")
cle.imshow(label_image, labels=True)
../_images/51805c923c35709f24d6f0350c13be42a832a6352c02b05b0d89eb7504a3320d.png

En mesurant l’intensité maximale dans l’image, nous pouvons voir que cette image étiquetée contenant 4 étiquettes n’est évidemment pas étiquetée séquentiellement.

np.max(label_image)
8

Nous pouvons utiliser la fonction unique pour déterminer quelles étiquettes sont présentes :

np.unique(label_image)
array([0, 1, 2, 4, 8], dtype=uint8)

Étiquetage séquentiel#

Nous pouvons maintenant ré-étiqueter cette image et supprimer ces écarts en utilisant la fonction relabel_sequential() de scikit-image. Nous utilisons _ comme variables de retour supplémentaires car nous ne sommes pas intéressés par elles. C’est nécessaire car la fonction relabel_sequential renvoie trois éléments, mais nous n’avons besoin que du premier.

relabeled, _, _ = relabel_sequential(label_image)

cle.imshow(relabeled, labels=True)
../_images/3ba6457cc995726598ebdc81386238075079725fa050bfd766321b040c813966.png

Ensuite, les étiquettes uniques devraient être séquentielles :

np.unique(relabeled)
array([0, 1, 2, 3, 4], dtype=uint8)

Pyclesperanto dispose également d’une fonction pour ré-étiqueter séquentiellement les images étiquetées. Le résultat est censé être identique à celui de scikit-image. Il ne renvoie simplement pas les valeurs supplémentaires.

relabeled1 = cle.relabel_sequential(label_image)

cle.imshow(relabeled1, labels=True)
../_images/3ba6457cc995726598ebdc81386238075079725fa050bfd766321b040c813966.png

Annulation de l’étiquetage séquentiel#

Dans certains cas, nous appliquons une opération à une image étiquetée qui renvoie une nouvelle image étiquetée avec moins d’étiquettes qui sont étiquetées séquentiellement, mais l’identité des étiquettes est perdue. Cela se produit par exemple lorsqu’on exclut de l’image étiquetée les étiquettes qui sont trop petites.

large_labels = cle.exclude_small_labels(relabeled, maximum_size=260)

cle.imshow(large_labels, labels=True, max_display_intensity=4)
../_images/36f7ec9698b614553fae93f11f9805517e0f0c5ff9395649d8a2f2a612d437b8.png
np.unique(large_labels)
array([0, 1, 2], dtype=uint32)

Pour restaurer les identités originales des étiquettes, nous devons multiplier une image binaire représentant les étiquettes restantes par l’image étiquetée originale.

binary_remaining_labels = large_labels > 0

cle.imshow(binary_remaining_labels)
../_images/c1423a2d9cd701d92e76baaea3eea0337cb0843c7be9208511df9b36b77de9ce.png
large_labels_with_original_identity = binary_remaining_labels * relabeled

cle.imshow(large_labels_with_original_identity, labels=True, max_display_intensity=4)
../_images/ba79843daab6429f7be86b46ff2fc6726f79e5eee587c077b33cea75b9e8f2fc.png
np.unique(large_labels_with_original_identity)
array([0., 1., 3.], dtype=float32)

Nous pouvons maintenant conclure que les étiquettes avec les identités 2 et 4 étaient trop petites et ont donc été exclues.