缩放#

图像缩放是预处理图像数据的一种聪明方法,理想情况下在去除噪声和背景之后进行。它允许将图像大小减小到仍然可以回答科学问题的程度,同时还能处理内存限制问题。例如,如果计算机报告内存不足错误,将图像缩小到较小的尺寸是继续项目的首选方法。此外,许多分割算法和定量测量方法都以像素/体素等距性为前提条件:体素在所有方向上必须具有相同的大小,否则此类算法的结果可能会产生误导或甚至是错误的。

import pyclesperanto_prototype as cle
import matplotlib.pyplot as plt
from skimage.io import imread

为了演示缩放,我们使用来自Broad Bio Image Challenge的裁剪和重采样图像数据: Ljosa V, Sokolnicki KL, Carpenter AE (2012). Annotated high-throughput microscopy image sets for validation. Nature Methods 9(7):637 / doi. PMID: 22743765 PMCID: PMC3627348. 可在 http://dx.doi.org/10.1038/nmeth.2083 获取

input_image = imread("../../data/BMP4blastocystC3-cropped_resampled_8bit.tif")

# 体素大小在所有方向上并不相等; 
# 体素是各向异性的。
voxel_size_x = 0.202
voxel_size_y = 0.202
voxel_size_z = 1

当沿三个轴可视化该数据集的投影时,你会看到体素并不是各向同性的。

def show(image_to_show, labels=False):
    """
    此函数生成三个投影:X、Y和Z方向,并显示它们。
    """
    projection_x = cle.maximum_x_projection(image_to_show)
    projection_y = cle.maximum_y_projection(image_to_show)
    projection_z = cle.maximum_z_projection(image_to_show)

    fig, axs = plt.subplots(1, 3, figsize=(10, 10))
    cle.imshow(projection_x, plot=axs[0], labels=labels)
    cle.imshow(projection_y, plot=axs[1], labels=labels)
    cle.imshow(projection_z, plot=axs[2], labels=labels)
    axs[0].set_title("ZY平面")
    axs[1].set_title("XZ平面")
    axs[2].set_title("XY平面")
    plt.show()

show(input_image)
../_images/7f1987918237ea9ff23fbb7d380ebf47a8288bf1a5b045ebc1e76a12908496a1.png

使用体素大小进行缩放#

解决这个问题最简单的方法是用体素大小来缩放数据集。根据定义,这将产生一个体素在所有方向上都是各向同性的数据集,并且在所有方向上voxel_size = 1(在我们的例子中是微米)。

scale_factor_x = voxel_size_x
scale_factor_y = voxel_size_y
scale_factor_z = voxel_size_z

resampled = cle.scale(input_image, 
                      factor_x=scale_factor_x, 
                      factor_y=scale_factor_y, 
                      factor_z=scale_factor_z, 
                      linear_interpolation=True,
                      auto_size=True)

show(resampled)
../_images/014a3011f5f5842dab8a613a773abc67e8bd866b03e0690462bb220450bac968.png

重采样后的堆栈在X和Y方向上现在有更少的体素,这在准确分割对象时可能会成为问题。我们可以通过打印原始数据和重采样图像的形状来清楚地看到这一点。这是图像堆栈在深度-高度-宽度(Z-Y-X)方向上的大小。

input_image.shape
(86, 396, 393)
resampled.shape
(86, 80, 79)

一个潜在的解决方案是引入一个zoom_factor。它允许调整重采样图像的大小:

zoom_factor = 2

scale_factor_x = voxel_size_x * zoom_factor
scale_factor_y = voxel_size_y * zoom_factor
scale_factor_z = voxel_size_z * zoom_factor

resampled_zoomed = cle.scale(input_image, 
                      factor_x=scale_factor_x, 
                      factor_y=scale_factor_y, 
                      factor_z=scale_factor_z, 
                      linear_interpolation=True,
                      auto_size=True)

show(resampled_zoomed)
../_images/b59cf3d9905ea9e1d84814d9adf0aab31adcacbe80c2ea303caad4fdcfd3765e.png
resampled_zoomed.shape
(172, 160, 159)

在缩放/放大3D图像时,请记住内存限制。你可以在以下视图的右侧框中读取图像的大小。像上面的例子那样将图像放大2倍,会使3D堆栈的图像大小增加8倍(2x2x2)。

resampled
cle._ image
shape(86, 80, 79)
dtypefloat32
size2.1 MB
min0.0
max255.0
resampled_zoomed
cle._ image
shape(172, 160, 159)
dtypefloat32
size16.7 MB
min0.045749664
max255.0

练习#

增加缩放因子并重新运行上面的代码。在哪个缩放因子下程序会崩溃?如果不崩溃,生成的图像会有多大?你的显卡有多少内存?