Segmenting with Cellpose#
from cellpose import core, utils, io, models, metrics
from tifffile import imread, imwrite
from pathlib import Path
from skimage.transform import resize
import numpy as np
import napari
from tqdm import tqdm
Loading the data#
Below we load the videos and extract the channels.
Currently this assumes there are 4 channels present :
Channel 1: CSFE (pan-cell marker)
Tumor cells
T cells (slightly)
Channel 2: Actin + tubulin channel + NucView (caspace-3 marker)
T cells centrosomes (bright)
Dying tumor cells nuclei (bright, may be due to cross-talk with NucView)
Membrane of T cells and tumor cells (slightly)
Channel 3 : Calcium channel
Highlights active T cells very brightly
Only every 10 frames due to phototoxicity
Channel 4 : Brightfield channel
Currently unused
Note
Change the ìmage_path
to load a different video.
image_path = Path("../DATA/series003_cCAR_tumor.tif")
image = imread(image_path)
image_actin_channel = image[:, 1, ...]
image_calcium_channel = image[:, 2, ...]
image = image[:, 0, ...]
image.shape
(162, 1412, 1412)
Resizing the image#
Below we downsample the images by a factor of two. This speeds up the segmentation greatly while only having a small cost on precision, as labels can be upsampled later again.
image_resized = resize(image, (image.shape[0], image.shape[1] // 2, image.shape[2] // 2), anti_aliasing=True)
image_actin_resized = resize(image_actin_channel, (image_actin_channel.shape[0], image_actin_channel.shape[1] // 2, image_actin_channel.shape[2] // 2), anti_aliasing=True)
image_calcium_resized = resize(image_calcium_channel, (image_calcium_channel.shape[0], image_calcium_channel.shape[1] // 2, image_calcium_channel.shape[2] // 2), anti_aliasing=True)
# v = napari.Viewer()
c:\Users\Cyril\anaconda3\envs\napari-cellpose\lib\site-packages\napari_tools_menu\__init__.py:194: FutureWarning: Public access to Window.qt_viewer is deprecated and will be removed in
v0.5.0. It is considered an "implementation detail" of the napari
application, not part of the napari viewer model. If your use case
requires access to qt_viewer, please open an issue to discuss.
self.tools_menu = ToolsMenu(self, self.qt_viewer.viewer)
# v.add_image(image_resized, name="image", colormap="viridis")
# v.add_image(image_actin_resized, name="actin", colormap="magma")
# v.add_image(image_calcium_resized, name="calcium", colormap="turbo")
<Image layer 'calcium' at 0x1a1a6a994f0>
Segmentation#
Loading the model#
Note
For segmenting cells as marked by CSFE, it is recommended to use the cyto3
model. Other models are available for various modalities however.
cellpose_model = models.CellposeModel(gpu=False, model_type='cyto3')
C:\Users\Cyril\AppData\Roaming\Python\Python38\site-packages\torch\_utils.py:776: UserWarning: TypedStorage is deprecated. It will be removed in the future and UntypedStorage will be the only storage class. This should only matter to you if you are using storages directly. To access UntypedStorage directly, use tensor.untyped_storage() instead of tensor.storage()
return self.fget.__get__(instance, owner)()
Generating the masks#
Below is the code for Cellpose inference. We use channels=[0,0]
, which must be used when segmenting grayscale images.
Important
The main parameters in CellPose inference are :
diameter
: The diameter of the cells in pixels. This is used to initialize the model. This is especially crucial, using napari you can use View > Scale bar to measure the diameter of the cells in pixels. The default is 30, for the current data (downsampled by 2), we find 45 to be a good value.flow_threshold
: The threshold for the flow field. This is used to determine if a cell is present or not. The default is 0.4, but this can be adjusted based on the data. A lower value will result in more cells being detected, but also more false positives.cellprob_threshold
: The threshold for the cell probability. This is used to filter out low-confidence detections. The default is 0.0, but increasing this value can help reduce false positives. Note that the range of values is [-8, 8], unlike many thresholds in image processing where the range is [0, 1].
masks = np.zeros_like(image_resized, dtype=np.uint16)
for i in tqdm(range(image_resized.shape[0])):
if i != 50:
break
masks[i], flows, styles = cellpose_model.eval(
image_resized[i], diameter=45, do_3D=False, channels=[0, 0], normalize=True, flow_threshold=0.8, cellprob_threshold=-1.0
)
masks = masks[0]
Saving the results#
imwrite("./results", masks.astype(np.uint16))