Erkennung lokaler Maxima#

Zur Erkennung lokaler Maxima, also Pixel, die von Pixeln mit geringerer Intensität umgeben sind, können wir einige Funktionen in scikit-image und clesperanto verwenden.

Siehe auch

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

Wir beginnen mit dem Laden eines Bildes und schneiden einen Bereich für Demonstrationszwecke aus. Wir haben den Bildsatz BBBC007v1 Version 1 verwendet (Jones et al., Proc. ICCV Workshop on Computer Vision for Biomedical Image Applications, 2005), der von der Broad Bioimage Benchmark Collection verfügbar ist [Ljosa et al., Nature Methods, 2012].

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

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

Vorverarbeitung#

Ein üblicher Vorverarbeitungsschritt vor der Erkennung von Maxima ist das Weichzeichnen des Bildes. Dies macht Sinn, um zu vermeiden, dass Maxima erkannt werden, die nur Intensitätsschwankungen aufgrund von Rauschen sind.

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

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

peak_local_max#

Die peak_local_max Funktion ermöglicht es, Maxima zu erkennen, die eine höhere Intensität als umgebende Pixel und andere Maxima gemäß einem definierten Schwellenwert haben.

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)

Diese Koordinaten können mit der Plot-Funktion von matplotlib visualisiert werden.

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

Wenn zu viele Maxima erkannt werden, kann man die Ergebnisse durch Änderung des sigma-Parameters der Gaußschen Unschärfe oben oder durch Änderung des Schwellenwerts, der an die Funktion peak_local_max übergeben wird, modifizieren.

detect_maxima_box#

Die Funktion peak_local_max neigt dazu, lange zu dauern, z.B. bei der Verarbeitung großer 3D-Bilddaten. Daher soll eine Alternative vorgestellt werden: clesperanto’s detect_maxima_box ist ein Bildfilter, der Pixel auf den Wert 1 setzt, falls umgebende Pixel eine geringere Intensität haben. Er ist typischerweise auch bei großen 3D-Bilddaten schnell.

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

Offensichtlich ergibt dies ein Binärbild. Dieses Binärbild kann in ein Labelbild umgewandelt werden, indem einzelne Spots mit verschiedenen Nummern gekennzeichnet werden. Aus diesem Labelbild können wir Maxima entfernen, die an Bildrändern erkannt wurden, was in diesem Fall nützlich sein könnte.

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

Um diese Spots auf dem Originalbild zu visualisieren, könnte es sinnvoll sein, die Größe der Spots zu erhöhen - nur für Visualisierungszwecke.

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

In der unteren Mitte dieses Bildes sehen wir jetzt ein lokales Maximum, das im Hintergrund erkannt wurde. Wir können diese Maxima in Bereichen niedrigerer Intensität durch Schwellenwertbildung entfernen.

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

Wir können jetzt Labels aus dem Spots-Bild ausschließen, bei denen die Intensität im Binärbild nicht im Bereich [0..1] liegt.

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

Wir können dann die Spots erneut mit der oben vorgestellten Strategie visualisieren, diesmal jedoch auf dem Originalbild.

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