Midiendo distancias entre objetos#

Este cuaderno demuestra cómo medir la distancia de objetos en una imagen al objeto más cercano en otra imagen. Un caso de uso para esto es medir la distancia de objetos como células a un vaso. El siguiente procedimiento se demuestra en 2D y debería funcionar de manera análoga en 3D.

import numpy as np
import pyclesperanto_prototype as cle
import napari_simpleitk_image_processing as nsitk
import pandas as pd

Como datos de ejemplo, usamos dos imágenes sintéticas: una imagen binaria que muestra dónde hay un vaso como una franja, y una imagen de etiquetas que muestra dónde están las células / objetos.

vessel = np.asarray([
    [0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 0, 1, 1, 1, 0, 0, 0, 0],
    [0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
    [0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
])

objects = np.asarray([
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 5, 5],
    [0, 0, 0, 0, 2, 0, 0, 0, 5, 5],
    [0, 4, 4, 0, 0, 0, 3, 0, 0, 0],
    [0, 4, 4, 0, 0, 0, 3, 0, 0, 0],
])

cle.imshow(vessel, continue_drawing=True)
cle.imshow(objects, labels=True, alpha=0.7)
../_images/c0cfac3fba21d7ff47458094e99b430ffa3b333ddcee645acd6d76186ea4351f.png

Mapas de distancia#

Para medir la distancia promedio de píxeles etiquetados a algún otro objeto, una estrategia implica mapas de distancia. Aquí usamos el mapa de distancia de Maurer firmado implementado en SimpleITK. Más precisamente, usamos el plugin napari programable napari-simpleitk-image-processing para acceder a ese mapa. Si los valores son positivos, estamos fuera del vaso. Los valores negativos sugieren que estamos dentro.

not_vessel = cle.binary_not(vessel)

distance_from_vessel = nsitk.signed_maurer_distance_map(not_vessel)

cle.imshow(distance_from_vessel, colorbar=True, colormap="jet")
../_images/b33a02ff5f61b3265a39cf451fe935a438924951fedef22a3b7937b9937f9b4c.png

Mapa de distancia de objetos#

A continuación, medimos la intensidad promedio en el mapa de distancia donde están los objetos. Estas intensidades representan la distancia promedio de estos objetos al vaso. La intensidad de fondo en estos mapas (distancia en nuestro caso) es 0, por definición.

mean_distance_map = cle.mean_intensity_map(distance_from_vessel, objects)

cle.imshow(mean_distance_map, colorbar=True, colormap="jet")
../_images/4cd86f25e183c16a9c5e450cb190f8c3223d6fac0d3f5b10c45adc6da1db78fa.png

Alternativamente a esta visualización, también podemos leer la distancia promedio utilizando estadísticas de píxeles e imprimirlas usando un DataFrame de pandas.

statistics = cle.statistics_of_labelled_pixels(distance_from_vessel, objects)

table = pd.DataFrame(statistics)
table = table[['label', 'mean_intensity']]
table = table.rename(columns={'mean_intensity':'mean_distance'})

table
label mean_distance
0 1 0.853553
1 2 -1.000000
2 3 1.000000
3 4 -0.500000
4 5 2.599586

Filtrando objetos#

También puedes filtrar objetos según su distancia al vaso.

min_distance = -4
max_distance = 2
objects_close_by_vessel = cle.exclude_labels_with_map_values_out_of_range(
    mean_distance_map,
    objects,
    minimum_value_range=min_distance,
    maximum_value_range=max_distance
)

cle.imshow(vessel, continue_drawing=True)
cle.imshow(objects_close_by_vessel, labels=True, alpha=0.7)
../_images/481caaa883d7a0eac25e7064502fb105f8038b6111cca43c16ac31ba1388bb17.png