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 :

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)
shape(100, 100)
dtypeuint16
size19.5 kB
min0
max1

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)
../_images/1ad67129c206bdc4a56ed95e7952eae43e2a96ccac52a8df8f6b0f25095f2d17.png

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
shape(100, 100)
dtypeuint16
size19.5 kB
min0
max1

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
shape(100, 100)
dtypebool
size9.8 kB
minFalse
maxTrue

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
shape(100, 100)
dtypefloat32
size39.1 kB
min-68.35203
max0.0

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.