如何渲染一个基础的Dicom文件(含演示)

1,267 阅读3分钟

⛳️ ⛳️ ⛳️ 本专栏为从0上手Cornerstone3D系列文章,包括cornerstone核心概念、基础使用、常见案例、工具使用、运行原理、源码解读等等

🚀 🚀 🚀 欢迎Star演示代码库Github(持续更新):github.com/jianyaoo/vu… ,交流更多相关使用技巧 ~

一、Cornerstone3D 是什么?

https://img-blog.csdnimg.cn/direct/d6f1bbeeab5c4f61b404a1f50d36a06d.png

二、代码示例

了解了Cornerstone是什么,有什么作用后,我们先看一下如何去渲染两种比较重要的影像,栈影像和Volume影像,感受一下代码的逻辑及运行顺序,先有个初始的了解。

1. 渲染一个栈图的核心片段

// 准备一个渲染引擎 => renderingEngine
const renderingEngine = new RenderingEngine(this.renderingEngineId);

// 在渲染引擎中创建并加载视图,使视图与HTML元素绑定
const viewportId = "CT_AXIAL_STACK";
const viewportInput = {
  viewportId: viewportId,
  element: document.querySelector("#element1"),
  type: csEnums.ViewportType.STACK,
};
renderingEngine.enableElement(viewportInput);

const viewport = renderingEngine.getViewport(viewportId);
viewport.setStack(imageIds, 60);
viewport.render();

2. 渲染一个Volume图的核心代码


// 准备一个渲染引擎 => renderingEngine
const renderingEngine = new RenderingEngine(this.renderingEngineId);

// 去创建并缓存一个Volume
const volume = await volumeLoader.createAndCacheVolume(this.volumeId, {
  imageIds,
});

// 在渲染引擎中创建并加载视图,使视图与HTML元素绑定
const viewportId1 = "CT_AXIAL";
const viewportId2 = "CT_SAGITTAL";
const viewportId3 = "CT_CORONAL";
const viewportInputArray = [
  {
    viewportId: viewportId1,
    type: csEnums.ViewportType.ORTHOGRAPHIC,
    element: document.querySelector("#element1"),
    defaultOptions: {
      orientation: csEnums.OrientationAxis.AXIAL,
    },
  },
  {
    viewportId: viewportId2,
    type: csEnums.ViewportType.ORTHOGRAPHIC,
    element: document.querySelector("#element2"),
    defaultOptions: {
      orientation: csEnums.OrientationAxis.SAGITTAL,
    },
  },
  {
    viewportId: viewportId3,
    type: csEnums.ViewportType.ORTHOGRAPHIC,
    element: document.querySelector("#element3"),
    defaultOptions: {
      orientation: csEnums.OrientationAxis.CORONAL,
    },
  },
];
renderingEngine.setViewports(viewportInputArray);

// 加载Volume => 注意:创建是创建,加载是加载,加载时才会去请求Dicom文件
volume.load();

// 在视图上设置Volume
await setVolumesForViewports(
  renderingEngine,
  [
    {
      volumeId: this.volumeId,
    },
  ],
  [viewportId1, viewportId2, viewportId3]
);

// 渲染图像
renderingEngine.renderViewports([viewportId1, viewportId2, viewportId3]);

三、渲染流程解析

我们在有了初始印象后,就要开始看一下它具体是如何执行的。如果想要在自己的项目中使用这个库应该如何去做,下面对渲染流程在步骤上进行一个详解的解读,至于运行原理会在后面源码解析篇展开。

  • 👉 在项目中安装Cornerstone3D库
# 关注node版本,较低版本(16.10以下)可能会安装失败
npm install @cornerstonejs/core
npm install @cornerstonejs/tools
npm install @cornerstonejs/streaming-image-volume-loader
  • 👉 准备Dom元素及加载的Dicom文件

Cornerstone官网已部署了一部分测试Dicom文件,相关调用可查看演示代码

  <div id="demo-wrap">
    <div id="element1" class="cornerstone-item"></div>
    <div id="element2" class="cornerstone-item"></div>
    <div id="element3" class="cornerstone-item"></div>
  </div>
  • 👉 准备一个渲染引擎 => renderingEngine
const renderingEngine = new RenderingEngine(this.renderingEngineId);
  • 👉 创建并缓存一个Volume
const volume = await volumeLoader.createAndCacheVolume(this.volumeId, {
  imageIds,
});
  • 👉 在渲染引擎中创建并加载视图,使视图与HTML元素绑定
const viewportId1 = "CT_AXIAL";
const viewportId2 = "CT_SAGITTAL";
const viewportId3 = "CT_CORONAL";
const viewportInputArray = [
{
  viewportId: viewportId1,
  type: csEnums.ViewportType.ORTHOGRAPHIC,
  element: document.querySelector("#element1"),
  defaultOptions: {
    orientation: csEnums.OrientationAxis.AXIAL,
  },
},
{
  viewportId: viewportId2,
  type: csEnums.ViewportType.ORTHOGRAPHIC,
  element: document.querySelector("#element2"),
  defaultOptions: {
    orientation: csEnums.OrientationAxis.SAGITTAL,
  },
},
{
  viewportId: viewportId3,
  type: csEnums.ViewportType.ORTHOGRAPHIC,
  element: document.querySelector("#element3"),
  defaultOptions: {
    orientation: csEnums.OrientationAxis.CORONAL,
  },
},
];
renderingEngine.setViewports(viewportInputArray);
  • 👉 加载Volume => 注意:创建是创建,加载是加载,加载时才会去请求Dicom文件
 volume.load();
  • 👉 在视图上设置Volume
  await setVolumesForViewports(
    renderingEngine,
    [
      {
        volumeId: this.volumeId,
      },
    ],
    [viewportId1, viewportId2, viewportId3]
  );
  • 👉 渲染图像
renderingEngine.renderViewports([viewportId1, viewportId2, viewportId3]);
  • 🎉 bingo 渲染结果

https://img-blog.csdnimg.cn/direct/390a0f3c7ec44172b469e7915cc19ed4.png

四、核心概念解析

当然,上面的代码虽然运行成功了,但是还是要刨根问底,知道每个步骤涉及到的核心点是什么,有什么作用,做到知己知彼,才能在我们的代码中少踩坑。下面是涉及到的几个核心的基础概念解读

1. ImageId

https://img-blog.csdnimg.cn/direct/6578d9db9d3c47c3886d001e5a67578c.png

imageLoader

https://img-blog.csdnimg.cn/direct/7b18f35a2c4242e6bc856dce69d6a985.png

RenderingEngine

https://img-blog.csdnimg.cn/direct/e97de77193bd47cbb6516f0b9af29014.png

🎧 结语

配套可运行代码演示:github.com/jianyaoo/vu…

clone到本地后直接运行 npm run serve 即可启动,目前支持演示功能如下,持续更新,欢迎star~

2.png

3.png