在這個教程中,我們將展示如何應(yīng)用組織結(jié)構(gòu)的細胞分割算法Cellpose(包含在squidpy.im.segment)進行空間轉(zhuǎn)錄組數(shù)據(jù)圖像的細胞核分割。
首先我得安裝安裝這個算法包pip install cellpose, 如果想局部環(huán)境下運行該包,可以建立單獨的conda環(huán)境conda env create -f cellpose_environment.yml該環(huán)境中需要安裝有 Squidpy和Cellpose.
import squidpy as sq
import numpy as np
import matplotlib.pyplot as plt
利用Cellpose準(zhǔn)備傳統(tǒng)的細胞分割算法
from cellpose import models
sq.im.segment方法參數(shù)接受幾個特征:numpy.ndarray (height, width, channels) 以及其它參數(shù)。為了運行cellpose模塊,我們定義了一個封裝函數(shù)來啟用該模塊,評估該模塊并返回分割mask。我們可以使用cellpose特定的選項,比如傳入特定的參數(shù)(min_size,每個mask中包含的最小數(shù)目的像素
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)

對DAPI通道應(yīng)用上述
cellpose函數(shù)處理,注意channel為0.sq.im.segment(img=crop, layer="image", channel=0, method=cellpose)畫出分割圖像后的DAPI通道以及相應(yīng)的細胞核分割的結(jié)果
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")

sq.im.segment方法傳遞cellpose方法,也可以過濾小于200像素的分割元件,并與上述默認參數(shù)為過濾小于15的結(jié)果進行對比。
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")

Cell segmentation on H&E stained tissue data
對于熒光圖像,我們可以對DAPI通道進行提取并且應(yīng)用于Cellpose模塊,但是對于HE圖像,我們只能將三個通道一起傳入(應(yīng)用sq.im.segment()附帶channel = None),并在Cellpose模塊中使用第一個通道參數(shù)決定我們對哪一個通道進行分割。這里,我們需要注意不同的通道有著不同的標(biāo)識:0=grayscale, 1=red, 2=green, 3=blue!
并且,對于HE圖像,我們需要通過設(shè)置invert=True來Invert圖像的顏色值,此外,使用初始的值只會識別到部分的細胞,需要去擴展Cellpose的參數(shù)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)

對于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")

我們需要提高敏感性,并傳入
flow_threshold=0.8來增到被檢測到的細胞核數(shù)目。
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")

接著測試傳入灰階圖像是否可以提高檢測效果
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")

同樣
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")
