Seuillage#
Le seuillage est une technique de segmentation d’image. Elle sépare une image à canal unique donnée (ou pile) en deux régions : les pixels dont l’intensité est inférieure à un seuil donné, également appelé “arrière-plan”, et les pixels dont l’intensité est supérieure à un seuil donné, “premier plan”. Typiquement, ces algorithmes produisent des images binaires où l’intensité de l’arrière-plan est 0 et l’intensité du premier plan est 1. Lors de l’application de tels algorithmes dans ImageJ, les pixels du premier plan sont 255. Dans scikit-image, les pixels d’arrière-plan sont False et les pixels de premier plan sont True.
Voir aussi
from skimage.io import imread
from pyclesperanto_prototype import imshow
import pyclesperanto_prototype as cle
from skimage import filters
from skimage.filters import try_all_threshold
from matplotlib import pyplot as plt
import napari_simpleitk_image_processing as nsitk
image = imread("../../data/blobs.tif")
imshow(image)
Segmentation d’image par seuillage#
L’opération threshold_otsu, également connue sous le nom de méthode d’Otsu (Otsu et al., IEEE Transactions on Systems, Man, and Cybernetics, Vol. 9 (1), 1979), fournit un nombre - le seuil à appliquer.
threshold = filters.threshold_otsu(image)
Lors de l’utilisation de méthodes telles que le seuillage dans les notebooks, il est recommandé d’imprimer le résultat pour voir ce qu’il retourne réellement. Ici, nous utilisons la méthode de scikit-image, qui renvoie le seuil qui est appliqué. L’impression de ce seuil peut être utile plus tard lors de la reproduction du flux de travail, également si d’autres veulent appliquer le même seuil à l’ensemble de données dans d’autres logiciels.
threshold
120
En utilisant des tableaux numpy, nous pouvons appliquer le seuil en utilisant l’opérateur >=. Le résultat sera une image binaire.
binary_image = image >= threshold
imshow(binary_image)
Nous pouvons également déterminer dans quel type l’image binaire est traitée en imprimant le minimum et le maximum de l’image :
binary_image.max()
True
binary_image.min()
False
Comme montré précédemment, matplotlib nous permet de dessiner un contour sur une image visualisée à l’aide de imshow en utilisant la commande contour.
# créer un nouveau graphique
fig, axes = plt.subplots(1,1)
# ajouter deux images
axes.imshow(image, cmap=plt.cm.gray)
axes.contour(binary_image, [0.5], linewidths=1.2, colors='r')
<matplotlib.contour.QuadContourSet at 0x2b57076dc70>
Il existe une liste d’algorithmes de seuillage disponibles. Il est possible de les appliquer tous à vos données et de voir les différences :
fig, ax = try_all_threshold(image, figsize=(10, 8), verbose=False)
plt.show()
Seuillage utilisant pyclesperanto#
De plus, d’autres bibliothèques telles que pyclesperanto offrent également des algorithmes de seuillage. L’implémentation ici ne renvoie pas le seuil, elle renvoie directement l’image binaire.
binary_image2 = cle.threshold_otsu(image)
imshow(binary_image2)
Ici, nous pouvons également voir que différentes bibliothèques stockent les images binaires de différentes manières. pyclesperanto, par exemple, stocke les pixels positifs dans les images binaires non pas comme True mais avec un 1 à la place :
binary_image2.max()
1.0
binary_image2.min()
0.0
Seuillage utilisant SimpleITK#
SimpleITK propose également des algorithmes de seuillage qui peuvent être trouvés dans la liste des filtres. Pour faciliter le script, nous utilisons ici napari-simpleitk-image-processing, un plugin napari scriptable qui offre certaines fonctions SimpleITK de manière plus accessible. Nous pouvons programmer une petite boucle for qui essaie tous les algorithmes de seuillage dans SimpleITK et nous montre les résultats :
threshold_algorithms = [
nsitk.threshold_huang,
nsitk.threshold_intermodes,
nsitk.threshold_isodata,
nsitk.threshold_kittler_illingworth,
nsitk.threshold_li,
nsitk.threshold_maximum_entropy,
nsitk.threshold_moments,
nsitk.threshold_otsu,
nsitk.threshold_renyi_entropy,
nsitk.threshold_shanbhag,
nsitk.threshold_triangle,
nsitk.threshold_yen
]
for algorithm in threshold_algorithms:
# afficher le nom de l'algorithme au-dessus de l'image
print(algorithm.__name__)
# binariser l'image en utilisant l'algorithme donné
binary_image = algorithm(image)
# montrer le résultat de la segmentation
imshow(binary_image)
threshold_huang
threshold_intermodes
threshold_isodata
threshold_kittler_illingworth
threshold_li
threshold_maximum_entropy
threshold_moments
threshold_otsu
threshold_renyi_entropy
threshold_shanbhag
threshold_triangle
threshold_yen
Exercice#
Segmentez blobs.tif en utilisant l’algorithme de Yen. Utilisez matplotlib pour dessiner un contour vert des objets segmentés autour des régions sur l’image originale.
Segmentez l’image en utilisant un seuil calculé selon cette équation :
threshold = mean + 2 * standard_deviation
Visualisez la segmentation résultante avec un contour rouge sur l’image originale et le contour vert de ci-dessus.
Alternativement, mettez les deux résultats de segmentation dans napari et comparez-les visuellement.