跳到主要内容

体数据渐进式加载

体数据视口的交错解码​

对体数据视口来说,我们大多是在渲染实际体数据的重建视图(MPR), 因此理想情形是尽快拿到该体数据最初的那些影像(即便是有损的), 以免渲染出一整块灰色的体数据。这一点可以通过交错取回请求来实现。

影像交错对体数据的任何编码方式都适用。也就是说,先取每第 N 张影像, 就能显示出一个频率为 1/N 的影像。交错代码随后只需把这些影像复制到 缺失的位置上,就得到一个纵向低分辨率的结果。

这种交错还可以与任何「离散取回某张影像的有损版本」的方式结合—— 也就是那种非流式的解码方式,一次请求整体返回。

性能

在体数据视口上使用渐进式加载所带来的性能提升, 会随数据规模和 DICOMweb 服务端组件的能力有相当大的差异。

注意下面这些时间都不包含加载解码器的时间,那只在首次渲染时出现, 而且两种方式在这一点上是相近的。

类型数据量网络首帧渲染完成
HTJ2K 流式33 M4g2503 ms8817 ms
HTJ2K 字节范围33 M4g1002 ms8813 ms

HTJ2K 字节范围比纯 JLS 略慢一点,但它可以在任何支持 HTJ2K 和字节范围请求的 DICOMweb 服务器上使用。

  • 4g 速率 —— 下行 30 mbit/s,上行 5 mbit/s,延迟 10 ms
  • 完整尺寸影像为 512×512×174
  • 降分辨率影像为 128×128 且经有损压缩

HTJ2K 流式​

注意这套阶段模型会通过选择队列和请求优先级, 把不同视口在各个阶段的请求相互交错起来。这种交错并不完美—— 它交错的是阶段而不是单个请求——但呈现效果相当不错, 而且不需要在多份体数据之间编写复杂的协调逻辑。

正如在进阶取回配置中学到的, 我们可以借助 decimate、offset 和不同的优先级来实现交错。

抽取(Decimation)是指以偏移量 F 每隔 N 张取一张影像,记作 N/F。 例如 4/3 表示位置 3,7,11,...。这是通过按顺序执行以下各阶段实现的:

  • 初始影像 —— 位置 0、50%、100% 处的影像
  • 用 multipleFast 取回类型取 4/3 抽取的影像
    • 这一步完成后,就能显示出一份低分辨率的完整体数据
  • 用 multipleFast 取回类型取 4/1 抽取的影像
    • 把初始体数据的分辨率提升一倍
  • 用 multipleFinal 取 4/2 和 4/0 抽取的影像
    • 把那些复制出来的影像替换为全分辨率影像
  • 用 multipleFinal 取 4/3 和 4/1 抽取的影像
    • 把低分辨率影像替换为全分辨率影像

配置大致长这样:

stages: [
{
id: 'initialImages',
// positions 用于选取特定位置 —— 中间那张,以及第一张和最后一张
positions: [0.5, 0, -1],
// 这些用默认的渲染类型,它应当取回全分辨率
retrieveType: 'default',
// 使用 Interaction 队列
requestType: RequestType.INTERACTION,
// 优先级 10,最先执行
priority: 10,
// 用这份数据填充附近的帧
nearbyFrames: {....},
},
{
id: 'quarterThumb',
decimate: 4,
offset: 3,
retrieveType: 'multipleFast',
priority: 9,
nearbyFrames,
},
... 其他版本
// 用最终数据替换最初那批数据
{
id: 'finalFull',
decimate: 4,
offset: 3,
priority: 4,
retrieveType: 'multipleFinal',
},
],
  1. 以全分辨率取回最初就要显示的那些影像(第一张和最后一张)
  2. 先取每第 4 张影像的前 initialByteRange 个字节
  • 取字节范围 [0,64000]
  • 立刻显示部分分辨率版本
  • 用部分分辨率版本来显示附近的切片
  1. 其他步骤
  • 这里还有其他的部分分辨率与全分辨率视图,用来把数据补齐
  1. 取回第 2 步剩下的数据(不重新取已有数据)
  • 用完整数据替换掉第 2 步的低分辨率数据

HTJ2K 字节范围​

体数据的渐进式加载在基础的堆栈加载之上做了扩展, 增加了交错取回各张影像的能力,并在影像内部和影像之间 都从降分辨率版本做插值。也就是说,单张影像最初可能按 1/4 尺寸取回 (对 CT 来说是 256×256),而且只取最初要显示的那张加上每第 4 张, 其余影像由插值得出。这里采用的是复制插值,以把插值开销降到最低。 最后,在有损的初始版本取回完成后,再取回剩余的影像。

默认的取回顺序如下,其中 Decimate 描述的是所取影像之间的间隔 以及在该集合中的偏移量。

  • 初始影像,全分辨率
  • 4/3 抽取,部分分辨率
    • 对 -2…+1 范围内的影像做插值(最近邻)
  • 4/1 抽取,部分分辨率
  • 4/2 抽取,全分辨率
  • 4/4 抽取,全分辨率
  • 4/3 抽取,全分辨率
  • 4/1 抽取,全分辨率

若未配置部分分辨率,则顺序相同,只是最后两个阶段永远不会执行—— 因为部分分辨率那几步已经把它们加载过了。 这套做法确实能让插值结果非常快地呈现出来。