Mesurer la distance à une ligne centrale#
Une question fréquente est de savoir comment déterminer les distances des points par rapport au centre d’un objet segmenté. Pour cela, nous pouvons squelettiser l’objet, produire une carte de distance et lire les intensités de la carte de distance aux points donnés pour déterminer leur distance par rapport au squelette / ligne centrale.
Voir aussi :
https://scikit-image.org/docs/stable/auto_examples/edges/plot_skeleton.html
https://examples.itk.org/src/filtering/distancemap/maurerdistancemapofbinary/documentation
from skimage.io import imread
import napari_segment_blobs_and_things_with_membranes as nsbatwm
import napari_simpleitk_image_processing as nsitk
import numpy as np
import stackview
import pyclesperanto_prototype as cle
Point de départ : une image binaire#
Nous commençons par utiliser une image binaire qui ressemble à un bras.
binary_arm = imread("../../data/binary_arm.tif")
stackview.insight(binary_arm)
|
|
|
De plus, nous continuons avec une liste de coordonnées au format X/Y :
coordinates_xy = np.asarray([
[70, 80],
[70, 70],
[70, 60]]).T
Nous produisons ensuite une image étiquetée où les coordonnées données sont étiquetées. La première coordonnée (index=0 dans la liste) sera étiquetée avec 1, la deuxième avec 2, et ainsi de suite. Les pixels d’arrière-plan sont 0. Nous utilisons cette image étiquetée pour la visualisation et plus loin, nous l’utiliserons également pour effectuer la mesure.
# draw the coordinates into an image; for visualization purposes
blank_image = cle.create((binary_arm.shape))
labeled_spots = coordinate_visualization = cle.pointlist_to_labelled_spots(coordinates_xy, blank_image)
# show the labeled pixels on top of the binary image
cle.imshow(binary_arm, continue_drawing=True, max_display_intensity=1)
cle.imshow(labeled_spots, labels=True, alpha=0.6)
Prétraitement#
Avant de pouvoir squelettiser l’image, nous devons remplir les trous noirs dans la zone blanche.
filled_holes = nsitk.binary_fill_holes(binary_arm)
filled_holes
|
|
n-sitk made image
|
Squelettisation#
Le squelette d’une image binaire est une fine ligne au centre des zones blanches.
skeleton = nsbatwm.skeletonize(filled_holes)
skeleton
<__array_function__ internals>:200: RuntimeWarning: Converting input from bool to <class 'numpy.uint8'> for compatibility.
|
|
nsbatwm made image
|
Carte de distance#
Nous dessinons ensuite une Carte de Distance de Maurer Signée. Les cartes de distance sont des images où l’intensité représente la distance d’un pixel au pixel blanc le plus proche dans l’image binaire à partir de laquelle la carte de distance a été générée.
distance_map = nsitk.signed_maurer_distance_map(skeleton)
distance_map
|
|
n-sitk made image
|
En utilisant stackview.picker, nous pouvons survoler l’image avec la souris et lire les intensités. Cela ne fonctionne que dans un environnement de type Jupyter.
stackview.picker(distance_map, zoom_factor=3)
Mesures#
Nous pouvons maintenant lire l’intensité dans la carte de distance aux emplacements donnés des points étiquetés.
values_at_positions = cle.read_intensities_from_positions(coordinates_xy, distance_map)
np.asarray(values_at_positions)
array([[-15.033297 , -5.0990195, -4. ]], dtype=float32)
Exercice#
Utilisez la carte de distance sur l’image binary_arm pour déterminer la distance des trois points par rapport au bord du bras, plutôt qu’à la ligne centrale.