%matplotlib inline

Cell-segmentation for fluorescence images

This example shows how to use the high resolution tissue images to segment nuclei.

This information can be used to compute additional image features like cell count and cell size per spot (see examples_image_compute_segmentation_features). This example shows how to use squidpy.im.segment and explains the parameters you can use.

We provide a built-in segmentation model squidpy.im.SegmentationWatershed. In addition, you can use a custom segmentation function, like a pre-trained tensorflow.keras model, to perform the segmentation utilizing squidpy.im.SegmentationCustom.

Note that when using the provided segmentation model [‘watershed’]{.title-ref}, the quality of the cell-segmentation depends on the quality of your tissue images. In this example we use the DAPI stain of a fluorescence dataset to compute the segmentation. For harder cases, you may want to provide your own pre-trained segmentation model.

See also

import numpy as np

import matplotlib.pyplot as plt

import squidpy as sq

# load fluorescence tissue image
img = sq.datasets.visium_fluo_image_crop()

We crop the image to a smaller segment. This is only to speed things up, squidpy.im.segment can also process very large images (see examples_image_compute_process_hires).

crop = img.crop_corner(1000, 1000, size=1000)

The tissue image in this dataset contains four fluorescence stains. The first one is DAPI, which we will use for the nuclei-segmentation.

crop.show("image", channelwise=True)
../../../_images/8a21757e9321eb075e21f7b042a4e22bc4b70d4d58c41212c2fc181088618dd5.png

We segment the image with squidpy.im.segment using watershed segmentation (method = 'watershed'). With the arguments layer and channel we define the image layer and channel of the image that should be segmented.

With kwargs we can provide keyword arguments to the segmentation model. For watershed segmentation, we need to set a threshold to create the mask image. You can either set a manual threshold, or use automated Otsu thresholding. For this fluorescence image example, Otsu’s thresh works very well, thus we will use thresh = None. See examples_image_compute_segment_hne for an example where we use a manually defined threshold.

In addition, we can specify if the values greater or equal than the threshold should be in the mask (default) or if the values smaller to the threshold should be in the mask (geq = False).

sq.im.segment(
    img=crop, layer="image", channel=0, method="watershed", thresh=None, geq=True
)

The segmented crop is saved in the layer segmented_watershed. This behavior can be changed with the arguments copy and layer_added. The result of the segmentation is a label image that can be used to extract features like the number of cells from the image.

print(crop)
print(f"Number of segments in crop: {len(np.unique(crop['segmented_watershed']))}")

fig, axes = plt.subplots(1, 2)
crop.show("image", channel=0, ax=axes[0])
_ = axes[0].set_title("DAPI")
crop.show("segmented_watershed", cmap="jet", interpolation="none", ax=axes[1])
_ = axes[1].set_title("segmentation")
ImageContainer[shape=(1000, 1000), layers=['image', 'segmented_watershed']]
Number of segments in crop: 580
../../../_images/1854978eca937a8bee5cdf9840aef09ce3f9940ba63899be422ee14ccf8f47af.png