Détection des maxima locaux#

Pour détecter les maxima locaux, pixels entourés de pixels d’intensité plus faible, nous pouvons utiliser certaines fonctions dans scikit-image et clesperanto.

Voir aussi

from skimage.feature import peak_local_max
import pyclesperanto_prototype as cle
from skimage.io import imread, imshow
from skimage.filters import gaussian 
import matplotlib.pyplot as plt

Nous commençons par charger une image et recadrer une région à des fins de démonstration. Nous avons utilisé l’ensemble d’images BBBC007v1 version 1 (Jones et al., Proc. ICCV Workshop on Computer Vision for Biomedical Image Applications, 2005), disponible dans la Broad Bioimage Benchmark Collection [Ljosa et al., Nature Methods, 2012].

image = imread("../../data/BBBC007_batch/A9 p7d.tif")[-100:, 0:100]

cle.imshow(image)
../_images/8641a082f73416921fa012245d92e7dcb078bcb651b843865b416a1a714e51e0.png

Prétraitement#

Une étape de prétraitement courante avant de détecter les maxima est le floutage de l’image. Cela a du sens pour éviter de détecter des maxima qui ne sont que des variations d’intensité résultant du bruit.

preprocessed = gaussian(image, sigma=2, preserve_range=True)

cle.imshow(preprocessed)
../_images/a1fb76dec30384ba824f283d6040b30910372248319637e4af2d3cc6fb41ee32.png

peak_local_max#

La fonction peak_local_max permet de détecter les maxima qui ont une intensité plus élevée que les pixels environnants et les autres maxima selon un seuil défini.

coordinates = peak_local_max(preprocessed, threshold_abs=5)
coordinates
array([[23, 85],
       [11, 29],
       [41, 40],
       [88, 34],
       [72, 83],
       [69, 89],
       [31, 72],
       [75, 16],
       [80, 22],
       [ 6, 56]], dtype=int64)

Ces coordonnées peuvent être visualisées en utilisant la fonction plot de matplotlib.

cle.imshow(preprocessed, continue_drawing=True)
plt.plot(coordinates[:, 1], coordinates[:, 0], 'r.')
[<matplotlib.lines.Line2D at 0x2309908fbb0>]
../_images/6eabc8dfa98723116061ddb967031bf8ff8fb0b6e38bfc0a30276647794d298d.png

S’il y a trop de maxima détectés, on peut modifier les résultats en changeant le paramètre sigma du flou gaussien ci-dessus ou en modifiant le seuil passé à la fonction peak_local_max.

detect_maxima_box#

La fonction peak_local_max a tendance à prendre beaucoup de temps, par exemple lors du traitement de grandes données d’images 3D. Ainsi, une alternative sera présentée : detect_maxima_box de clesperanto est un filtre d’image qui attribue aux pixels la valeur 1 lorsque les pixels environnants ont une intensité plus faible. Il est généralement rapide même sur de grandes données d’images 3D.

local_maxima_image = cle.detect_maxima_box(preprocessed)
local_maxima_image
cle._ image
shape(100, 100)
dtypeuint8
size9.8 kB
min0.0
max1.0

Évidemment, cela donne une image binaire. Cette image binaire peut être convertie en une image étiquetée en attribuant des numéros différents aux spots individuels. À partir de cette image étiquetée, nous pouvons supprimer les maxima détectés aux bords de l’image, ce qui peut être utile dans ce cas.

all_labeled_spots = cle.label_spots(local_maxima_image)

labeled_spots = cle.exclude_labels_on_edges(all_labeled_spots)
labeled_spots
cle._ image
shape(100, 100)
dtypeuint32
size39.1 kB
min0.0
max11.0

Pour visualiser ces spots sur l’image originale, il peut être judicieux d’augmenter la taille des spots - juste à des fins de visualisation.

label_visualization = cle.dilate_labels(labeled_spots, radius=3)

cle.imshow(preprocessed, continue_drawing=True)
cle.imshow(label_visualization, labels=True, alpha=0.5)
../_images/8458205f2922ebc84185e00c56daf9cba55b7592be2b3208a0e9502710cf4c43.png

Dans la partie inférieure centrale de cette image, nous voyons maintenant un maximum local qui a été détecté dans l’arrière-plan. Nous pouvons supprimer ces maxima dans les régions de plus faible intensité par seuillage.

binary_image = cle.threshold_otsu(preprocessed)
binary_image
cle._ image
shape(100, 100)
dtypeuint8
size9.8 kB
min0.0
max1.0

Nous pouvons maintenant exclure les étiquettes de l’image des spots où l’intensité dans l’image binaire n’est pas dans la plage [0..1].

final_spots = cle.exclude_labels_with_map_values_out_of_range(
    binary_image,
    labeled_spots,
    minimum_value_range=1,
    maximum_value_range=1
)
final_spots
cle._ image
shape(100, 100)
dtypeuint32
size39.1 kB
min0.0
max10.0

Nous pouvons ensuite visualiser à nouveau les spots en utilisant la stratégie introduite ci-dessus, mais cette fois sur l’image originale.

label_visualization2 = cle.dilate_labels(final_spots, radius=3)

cle.imshow(image, continue_drawing=True)
cle.imshow(label_visualization2, labels=True, alpha=0.5)
../_images/ae780bf69815d2f1e8a6c74bf226ae08899765e680ce393270c28a47db834cb9.png