Skip to main content

体积数据的流式传输

随着 Volumes 被添加到 Cornerstone3D,我们正在添加和维护 Streaming-volume-image-loader,这是一个用于体积的渐进式加载器。此加载器旨在接受 imageIds 并将它们加载到 Volume 中。

从图像创建体积​

由于 3D Volume 由 2D 图像组成(在 StreamingImageVolume 中),其体积元数据来源于 2D 图像的元数据。因此,此加载器需要初始调用来获取图像元数据。通过这种方式,我们不仅可以预先分配并缓存内存中的 Volume,还可以在 2D 图像被加载时渲染体积(渐进式加载)。

通过预先获取所有图像(imageIds)的元数据,我们不需要为每个 imageId 创建 Image 对象。相反,我们可以将图像的 pixelData 直接插入到体积中的正确位置。这保证了速度和内存效率(但带来了预获取元数据的最低成本)。

将体积与图像相互转换​

StreamingImageVolume 基于一系列获取的图像(2D)加载体积,Volume 可以实现将其 3D 像素数据转换为 2D 图像的功能,而无需通过网络重新请求它们。例如,使用 convertToCornerstoneImage,StreamingImageVolume 实例接受一个 imageId 及其 imageId 索引,并返回一个 Cornerstone Image 对象(ImageId 索引是必需的,因为我们希望在 3D 数组中定位 imageId 的 pixelData 并将其复制到 Cornerstone Image 中)。

这是一个可以逆转的过程;如果一组 imageIds 具有体积的属性(相同的参考系、起点、维度、方向和像素间距),Cornerstone3D 可以从这些 imageIds 创建一个体积。

使用​

如前所述,应事先从图像元数据创建预缓存体积。这可以通过调用 createAndCacheVolume 来完成。

const ctVolumeId = 'cornerstoneStreamingImageVolume:CT_VOLUME';
const ctVolume = await volumeLoader.createAndCacheVolume(ctVolumeId, {
imageIds: ctImageIds,
});

然后,体积可以调用其 load 方法来实际加载图像的像素数据。

await ctVolume.load();

imageLoader​

由于体积加载器不需要为 StreamingImageVolume 中的每个 imageId 创建 Image 对象,它将内部使用 skipCreateImage 选项来跳过图像对象的创建。否则,体积的图像加载器与 cornerstone-wado-image-loader 中编写的 wadors 图像加载器相同。

const imageIds = ['wadors:imageId1', 'wadors:imageId2'];

const ctVolumeId = 'cornerstoneStreamingImageVolume:CT_VOLUME';

const ctVolume = await volumeLoader.createAndCacheVolume(ctVolumeId, {
imageIds: ctImageIds,
});

await ctVolume.load();

可考虑的替代实现​

尽管我们相信我们的预获取体积方法确保了体积尽可能快速地加载,但仍然可以有其他不依赖此预获取的体积加载器实现。

创建不预获取元数据的体积​

在这种情况下,每个图像需要单独创建,这意味着每个图像需要被加载并且应该创建一个 Cornerstone Image。这是一个昂贵的操作,因为所有图像对象都被加载到内存中,并且需要从这些图像单独创建一个 Volume。

优点:

  • 不需要单独的元数据调用来获取图像元数据。

缺点:

  • 性能成本
  • 无法渐进式加载图像数据,因为它需要为每个图像更改创建一个新的体积