场景:比较同一阈值算法的不同实现#

在本笔记本中,我们将比较同一算法的不同实现。作为示例,我们选择Otsu二值化阈值方法与连通组件标记相结合。该算法发表于40多年前,人们可能会认为这种算法的所有常见实现都会显示相同的结果。

另请参阅#

from skimage.io import imread, imshow, imsave
from skimage.filters import threshold_otsu
from skimage.measure import label
from skimage.color import label2rgb

实现1: ImageJ#

作为第一个实现,我们来看看ImageJ。我们将它作为Fiji发行版的一部分使用。以下ImageJ宏代码打开”blobs.tif”,使用Otsu方法对其进行阈值处理,并应用连通组件标记。结果标记图像被保存到磁盘。您可以通过单击File > New > Script在Fiji的脚本编辑器中执行此脚本。

注意: 执行此脚本时,您应该调整图像数据的路径,以便它可以在您的计算机上运行。

with open('blobs_segmentation_imagej.ijm') as f:
    print(f.read())
open("C:/structure/code/clesperanto_SIMposium/blobs.tif");

// binarization
setAutoThreshold("Otsu dark");
setOption("BlackBackground", true);
run("Convert to Mask");

// Connected component labeling + measurement
run("Analyze Particles...", "  show=[Count Masks] ");

// Result visualization
run("glasbey on dark");

// Save results
saveAs("Tiff", "C:/structure/code/clesperanto_SIMposium/blobs_labels_imagej.tif");

结果看起来是这样的:

imagej_label_image = imread("blobs_labels_imagej.tif")
visualization = label2rgb(imagej_label_image, bg_label=0)
imshow(visualization)
<matplotlib.image.AxesImage at 0x1d290a79520>
../_images/274cd5c9d29a0d56ef587d5388b15a01098442deaaae0bc67c53f90d483b63f9.png

实现2: scikit-image#

作为第二个实现,我们将使用scikit-image。由于它可以从jupyter笔记本中使用,我们也可以再次仔细查看工作流程。

我们首先加载并可视化原始blob图像。

blobs_image = imread("blobs.tif")
imshow(blobs_image, cmap="Greys_r")
C:\Users\rober\miniconda3\envs\bio_39\lib\site-packages\skimage\io\_plugins\matplotlib_plugin.py:150: UserWarning: Float image out of standard range; displaying image with stretched contrast.
  lo, hi, cmap = _get_display_range(image)
<matplotlib.image.AxesImage at 0x1d290cfd7c0>
../_images/8615d0d6587b65fbb39ad4e627fd8475dd7f2343dcdf7647aeda0f1e24d4e092.png

然后使用threshold_otsu方法对图像进行二值化。

# determine threshold
threshold = threshold_otsu(blobs_image)

# apply threshold
binary_image = blobs_image > threshold

imshow(binary_image)
<matplotlib.image.AxesImage at 0x1d290f67280>
../_images/d912d7acff68e20a54b7cdec9b1c9f50c7c341d650f6e3cffd287839452c4638.png

对于连通组件标记,我们使用label方法。标记图像的可视化是使用`` method产生的。

# connected component labeling
skimage_label_image = label(binary_image)

# visualize it in colours
visualization = label2rgb(skimage_label_image, bg_label=0)
imshow(visualization)
<matplotlib.image.AxesImage at 0x1d290d2f940>
../_images/aa39527ccd2e88578b56f997602c2e61f6202049925bd1045e7c872d01b815ff.png

为了稍后比较图像,我们还将这个图像保存到磁盘。

imsave("blobs_labels_skimage.tif", skimage_label_image)
C:\Users\rober\AppData\Local\Temp\ipykernel_6744\179771585.py:1: UserWarning: blobs_labels_skimage.tif is a low contrast image
  imsave("blobs_labels_skimage.tif", skimage_label_image)

实现3: clesperanto / python#

同一工作流程的第三个实现也从python运行,并使用pyclesperanto

注意: 执行此脚本时,您应该调整图像数据的路径,以便它可以在您的计算机上运行。

import pyclesperanto_prototype as cle

blobs_image = cle.imread("C:/structure/code/clesperanto_SIMposium/blobs.tif")

cle.imshow(blobs_image, "Blobs", False, 0, 255)

# Threshold Otsu
binary_image = cle.create_like(blobs_image)
cle.threshold_otsu(blobs_image, binary_image)

cle.imshow(binary_image, "Threshold Otsu of CLIJ2 Image of blobs.gif", False, 0.0, 1.0)

# Connected Components Labeling Box
label_image = cle.create_like(binary_image)
cle.connected_components_labeling_box(binary_image, label_image)

cle.imshow(label_image, "Connected Components Labeling Box of Threshold Otsu of CLIJ2 Image of blobs.gif", True, 0.0, 64.0)
../_images/07f150782728e957fcf976380051de87c0faa3adbc2c7ade8b12da32f107ee1d.png ../_images/aac24fde3fd260040b5033ca92c02ff51dae5ae320de2449b8e8e86ef339dc9d.png ../_images/177acdc0fce60609e9cc9d1df01ec420b31863a72853b11ca38319ae2e1f8e5d.png

我们也将保存这个图像以便稍后比较。

imsave("blobs_labels_clesperanto_python.tif", label_image)

实现4: clesperanto / Jython#

第四个实现在Fiji中使用clesperanto。要在Fiji中运行此脚本,请在您的Fiji中激活clij、clij2clijx-assistant更新站点。您可能会注意到此脚本与上面的脚本相同。只有保存结果的工作方式不同。

注意: 执行此脚本时,您应该调整图像数据的路径,以便它可以在您的计算机上运行。

with open('blobs_segmentation_clesperanto.py') as f:
    print(f.read())
# To make this script run in Fiji, please activate the clij, clij2
# and clijx-assistant update sites in your Fiji. 
# Read more: 
# https://clij.github.io/
# 
# To make this script run in python, install pyclesperanto_prototype:
# conda install -c conda-forge pyopencl
# pip install pyclesperanto_prototype
# Read more: 
# https://clesperanto.net
# 
import pyclesperanto_prototype as cle

blobs_image = cle.imread("C:/structure/code/clesperanto_SIMposium/blobs.tif")

cle.imshow(blobs_image, "Blobs", False, 0, 255)

# Threshold Otsu
binary_image = cle.create_like(blobs_image)
cle.threshold_otsu(blobs_image, binary_image)

cle.imshow(binary_image, "Threshold Otsu of CLIJ2 Image of blobs.gif", False, 0.0, 1.0)

# Connected Components Labeling Box
label_image = cle.create_like(binary_image)
cle.connected_components_labeling_box(binary_image, label_image)

cle.imshow(label_image, "Connected Components Labeling Box of Threshold Otsu of CLIJ2 Image of blobs.gif", True, 0.0, 64.0)

# The following code is ImageJ specific. If you run this code from 
# Python, consider replacing this part with skimage.io.imsave
from ij import IJ
IJ.saveAs("tif","C:/structure/code/clesperanto_SIMposium/blobs_labels_clesperanto_imagej.tif");

我们也来看看这个工作流程的结果:

imagej_label_image = imread("blobs_labels_clesperanto_imagej.tif")
visualization = label2rgb(imagej_label_image, bg_label=0)
imshow(visualization)
<matplotlib.image.AxesImage at 0x1d291513a90>
../_images/aa39527ccd2e88578b56f997602c2e61f6202049925bd1045e7c872d01b815ff.png