Latest release includes GPU support for the modules:
Still to do: ndfourier, ndmeasure, ndmorph*
*Done, pending cupy PR #3907
|Single CPU Core||2hr 39min|
|Forty CPU Cores||11min 30s|
|One GPU||1min 37s|
from dask_image.imread import imread images = imread('data/BBBC039/images/*.tif') # images_on_gpu = imread('data/BBBC039/images/*.tif', arraytype="cupy") images
from dask_image import ndfilters smoothed = ndfilters.gaussian_filter(images, sigma=[0, 1, 1])
absolute_threshold = smoothed > 160
# Let's have a look at the images import napari from napari.utils import nbscreenshot viewer = napari.Viewer() viewer.add_image(absolute_threshold) viewer.add_image(images, contrast_limits=[0, 2000]) nbscreenshot(viewer)
viewer.layers[-1].visible = False napari.utils.nbscreenshot(viewer)
thresh = ndfilters.threshold_local(smoothed, images.chunksize) threshold_images = smoothed > thresh
# Let's take a look at the images viewer.add_image(threshold_images) nbscreenshot(viewer)
These are operations on the shape of a binary image.
A morphological opening operation is an erosion, followed by a dilation.
from dask_image import ndmorph import numpy as np structuring_element = np.array([ [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 1, 0], [1, 1, 1], [0, 1, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]) binary_images = ndmorph.binary_opening(threshold_images, structure=structuring_element)
Each image has many individual nuclei, so for the sake of time we'll measure a small subset of the data.
from dask_image import ndmeasure # Create labelled mask label_images, num_features = ndmeasure.label(binary_images[:3], structuring_element) index = np.arange(num_features - 1) + 1 # [1, 2, 3, ...num_features] print("Number of nuclei:", num_features.compute())
Number of nuclei: 271
# Let's look at the labels viewer.add_labels(label_images) viewer.dims.set_point(0, 0) nbscreenshot(viewer)