在这个教程中,我们将展示如何应用组织结构的细胞分割算法Cellpose(包含在squidpy.im.segment
)进行空间转录组数据图像的细胞核分割。
首先我得安装安装这个算法包pip install cellpose
, 如果想局部环境下运行该包,可以建立单独的conda环境conda env create -f cellpose_environment.yml
该环境中需要安装有 Squidpy和Cellpose.
import squidpy as sq
import numpy as np
import matplotlib.pyplot as plt
利用Cellpose准备传统的细胞分割算法
from cellpose import models
sq.im.segment
方法参数接受几个特征:numpy.ndarray (height, width, channels) 以及其它参数。为了运行cellpose模块,我们定义了一个封装函数来启用该模块,评估该模块并返回分割mask。我们可以使用cellpose特定的选项,比如传入特定的参数(min_size,每个mask中包含的最小数目的像素
The method parameter of themethod accepts any callable with the signature: -> numpy.ndarray
(height, width[, channels]). Additional model specific arguments will also be passed on. To use the Cellpose model, we define a wrapper that initializes the model, evaluates it and returns the segmentation masks. We can make use of Cellpose specific options by passing on arguments like the minimum number of pixels per mask min_size
.
def cellpose(img, min_size=15):
model = models.Cellpose(model_type='nuclei')
res, _, _, _ = model.eval(
img,
channels=[0, 0],
diameter=None,
min_size=min_size,
)
return res
Cell segmentation on Visium fluorescence data
加载荧光图片并显示不同的通道
img = sq.datasets.visium_fluo_image_crop()
crop = img.crop_corner(1000, 1000, size=1000)
crop.show(channelwise=True)
图片.png
对DAPI通道应用上述
cellpose
函数处理,注意channel为0.sq.im.segment(img=crop, layer="image", channel=0, method=cellpose)
画出分割图像后的DAPI通道以及相应的细胞核分割的结果
print(crop)
print(f"Number of segments in crop: {len(np.unique(crop['segmented_custom']))}")
fig, axes = plt.subplots(1, 2, figsize=(10, 20))
crop.show("image", channel=0, ax=axes[0])
_ = axes[0].set_title("DAPI")
crop.show("segmented_custom", cmap="jet", interpolation="none", ax=axes[1])
_ = axes[1].set_title("Cellpose segmentation")
图片.png
sq.im.segment
方法传递cellpose
方法,也可以过滤小于200像素的分割元件,并与上述默认参数为过滤小于15的结果进行对比。
sq.im.segment(img=crop, layer="image", channel=0, method=cellpose, min_size=200)
print(crop)
print(f"Number of segments in crop: {len(np.unique(crop['segmented_custom']))}")
fig, axes = plt.subplots(1, 2, figsize=(10, 20))
crop.show("image", channel=0, ax=axes[0])
_ = axes[0].set_title("DAPI")
crop.show("segmented_custom", cmap="jet", interpolation="none", ax=axes[1])
_ = axes[1].set_title("Cellpose segmentation")
图片.png
Cell segmentation on H&E stained tissue data
对于荧光图像,我们可以对DAPI通道进行提取并且应用于Cellpose模块,但是对于HE图像,我们只能将三个通道一起传入(应用sq.im.segment()
附带channel = None
),并在Cellpose模块中使用第一个通道参数决定我们对哪一个通道进行分割。这里,我们需要注意不同的通道有着不同的标识:0=grayscale, 1=red, 2=green, 3=blue!
并且,对于HE图像,我们需要通过设置invert=True
来Invert图像的颜色值,此外,使用初始的值只会识别到部分的细胞,需要去扩展Cellpose的参数flow_threshold
.
def cellpose_he(img, min_size=15, flow_threshold=0.4, channel_cellpose=0):
model = models.Cellpose(model_type='nuclei')
res, _, _, _ = model.eval(
img,
channels=[channel_cellpose, 0],
diameter=None,
min_size=min_size,
invert=True,
flow_threshold=flow_threshold,
)
return res
img = sq.datasets.visium_hne_image_crop()
crop = img.crop_corner(0, 0, size=1000)
crop.show("image", channelwise=True)
图片.png
对于HE图像,我们测试只传入蓝色通道(image=0)channel_cellpose=1
sq.im.segment(img=crop, layer="image", channel=None, method=cellpose_he, channel_cellpose=1)
print(crop)
print(f"Number of segments in crop: {len(np.unique(crop['segmented_custom']))}")
fig, axes = plt.subplots(1, 2, figsize=(10, 20))
crop.show("image", channel=None, ax=axes[0])
_ = axes[0].set_title("H&E")
crop.show("segmented_custom", cmap="jet", interpolation="none", ax=axes[1])
_ = axes[1].set_title("Cellpose segmentation")
图片.png
我们需要提高敏感性,并传入
flow_threshold=0.8
来增到被检测到的细胞核数目。
sq.im.segment(img=crop, layer="image", channel=None, method=cellpose_he, flow_threshold=0.8, channel_cellpose=1)
print(crop)
print(f"Number of segments in crop: {len(np.unique(crop['segmented_custom']))}")
fig, axes = plt.subplots(1, 2, figsize=(10, 20))
crop.show("image", channel=None, ax=axes[0])
_ = axes[0].set_title("H&E")
crop.show("segmented_custom", cmap="jet", interpolation="none", ax=axes[1])
_ = axes[1].set_title("Cellpose segmentation")
图片.png
接着测试传入灰阶图像是否可以提高检测效果
channel_cellpose=0
sq.im.segment(img=crop, layer="image", channel=None, method=cellpose_he, channel_cellpose=0)
print(crop)
print(f"Number of segments in crop: {len(np.unique(crop['segmented_custom']))}")
fig, axes = plt.subplots(1, 2, figsize=(10, 20))
crop.show("image", channel=None, ax=axes[0])
_ = axes[0].set_title("H&E")
crop.show("segmented_custom", cmap="jet", interpolation="none", ax=axes[1])
_ = axes[1].set_title("Cellpose segmentation")
图片.png
同样
flow_threshold=0.8
sq.im.segment(img=crop, layer="image", channel=None, method=cellpose_he, flow_threshold=0.8, channel_cellpose=0)
print(crop)
print(f"Number of segments in crop: {len(np.unique(crop['segmented_custom']))}")
fig, axes = plt.subplots(1, 2, figsize=(10, 20))
crop.show("image", channel=None, ax=axes[0])
_ = axes[0].set_title("H&E")
crop.show("segmented_custom", cmap="jet", interpolation="none", ax=axes[1])
_ = axes[1].set_title("Cellpose segmentation")
图片.png
网友评论