如何使用cornerstone3D渲染3D影像

🍓 前言

在日常开发中经常会遇到除了渲染MPR视图外,还需要渲染3D扫描影像,本文从具体的实现、viewport type解读、场景预设等方面来介绍3D具体的实现及涉及到的相关概念。

🥑 效果演示

点击查看完整代码

🍒 实现及概念

代码实现

关于如何实现一个3D渲染,在我们准备了一组Dicom文件后,整体流程跟普通stack、MPR一致,主要代码如下:

js 复制代码
async function init() {
  await initCornerstone();
  
  const imageIds = await get3DTestImageId();
  
  const renderingEngine = new RenderingEngine(renderingEngineId);
  
  const volume = await volumeLoader.createAndCacheVolume(volumeId, {
    imageIds
  });
  
  const viewportInputArray = [
    {
      viewportId: viewportId,
      type: csEnums.ViewportType.VOLUME_3D, // ✅ 改动点1:这里修改为volume3D类型
      element: document.querySelector("#element1"),
      defaultOptions: {
        orientation: csEnums.OrientationAxis.CORONAL,
        background: CONSTANTS.BACKGROUND_COLORS.slicer3D
      }
    }
  ];
  renderingEngine.setViewports(viewportInputArray);

  await volume.load();
  
  await setVolumesForViewports(renderingEngine, [{ volumeId }], [viewportId]);
  
  const viewport = renderingEngine.getViewport(viewportId);
  
  //  ✅ 改动点2:在添加完viewoprt后,需要设置viewport的预设属性
  viewport.setProperties({
    preset: preset.value,
  });
  
  viewport.render();
}

这样,就可以渲染一个3D影像了 🎉 🎉,只关注代码实现的朋友可以直接跳过下面的踩坑记录和概念解读~

视图类型

我们在前面介绍MPR实现时,在创建viewport视图步骤中使用的type固定为 ViewportType.ORTHOGRAPHIC枚举值,那我们可以来看一下cornerstone中支持的视图类型具体都有哪些,在实现时又如何选择。

ViewportType中的全部枚举值及适用场景

  • 🎉 STACK:适用于呈现一堆图像,这些图像可能属于也可能不属于同一图像。Stack可以包含不同形状、大小和方向的二维图像。

  • 🎉 ORTHOGRAPHIC :适用于渲染被认为是一个3D图像的Volume数据。拥有VolumeViewport可以通过设计实现多平面重组或重建(MPR),在这种情况下,可以从不同的方向可视化体积,而不会增加性能成本。

  • PERSPECTIVE:透视图视图,目前Cornerstone暂未时间该视图功能

  • 🎉 VOLUME_3D :专门用于3D体积渲染(Volume Rendering),是一种用于可视化和分析三维医学图像数据(如CT或MRI扫描)的技术。VOLUME_3D 视图通过将2D切片数据构建成3D模型,允许用户以三维形式查看、旋转和操作医学影像,以便更好地理解和诊断。

  • 🎉 VIDEOVIDEO视图是一种专门用于显示和处理视频数据的视口(viewport)。与传统的静态图像或三维体积渲染不同,VIDEO视图处理的是动态的、多帧的影像数据。此类视图在医学影像领域尤其有用,因为许多医学影像设备(如超声波、心脏造影等)生成的都是视频形式的数据

  • WholeSlide:专门用于处理和显示全视野切片图像的视口。全视野切片图像通常应用于数字病理学领域,它是高分辨率的显微镜图像,通常由非常大尺寸的图像拼接而成,涵盖了整个组织切片。

在日常需求中,我们经常遇到的就是上面标注🎉 的四种,在渲染3D时我们用到的就是 VOLUME_3D 视图类型,可以允许将一组dicom文件以3D视图的形式展示

js 复制代码
  const viewportInputArray = [
    {
      viewportId: viewportId,
      type: csEnums.ViewportType.VOLUME_3D, // 设置视图类型
      element: document.querySelector("#element1"),
      defaultOptions: {
        orientation: csEnums.OrientationAxis.CORONAL, // 初始化时想要展示的方向
      }
    }
  ];
  renderingEngine.setViewports(viewportInputArray);

场景预设

在修改完视图类型后,兴致勃勃的重新执行了代码,结果发现渲染出来的是一个黑色立方体,上面飘着一个黑白色2D图,如下图所示。又重新回去调试了代码,但是发现又没有报错信息及告警提示 😱😱😱 ~

这个时候就需要了解preset场景预设了,在加载完viewport后,我们可以打印看一下默认情况下viewport的属性值有哪些?默认情况下视图只会有一个voi的默认值,其他的属性都为undefined。

colorMap属性在 Cornerstone渲染CT+PET融合影像及相关应用场景 一文中已经介绍过了,主要是针对2D场景进行颜色映射,那对于3D场景来说,我们就需要用到 preset 属性了。

preset属性通常指的是预设的显示参数或配置。这些预设参数用于控制3D模型在Cornerstone3D中的外观和行为。preset属性可以包括颜色、透明度、阴影、渲染模式等显示设置,以便快速应用特定的视觉效果或设置,而无需手动调整每个参数。

如果了解一些threeJs或者webGl相关的知识,那对于以上显示黑色长方体的情况就能更好的理解了。我们想要现实一个3D物体,那3D模型的颜色、透明度、显示模式、光照强度、视角等等参数都会影响图像的显示。如果没有光照(就类似于我们在晚上处于一间没有任何灯光的屋子里一样),那我们看到的就是漆黑一片。而preset属性的目的就是为了给viewport视图添加颜色、光照、透明度等设置,便于更好的显示3D模型。在cornerstone中内设了很多preset设置,支持查看不同需求下的3D影像。

js 复制代码
import {
  CONSTANTS,
} from "@cornerstonejs/core";

const presetOptions = CONSTANTS.VIEWPORT_PRESETS.map(item => item.name); // 获取到所有的预设场景

我们可以看一下预设的场景中都定义了哪些内容(以CT-Bone为例),便于我们更深入的了解3D显示(以下属性仅限了解即可,目前cornerstone3D暂不支持自定义预设场景,以下大部分概念词来源于threejs)

  • name: 当前预设的名称

  • gradientOpacity:定义了梯度不透明度的映射,通常用于控制图像中不同密度的区域(例如骨骼与软组织之间)的不透明度变化。数值对应于梯度值与其相应的不透明度。

  • specularPower:高光强度的控制参数。值为10表示高光的集中度,数值越高,高光越集中。

  • specular:镜面反射系数,决定表面的光亮度。值0.2表示表面有一定的镜面反射,但不非常亮

  • shade:是否启用阴影效果。值为1表示启用阴影,这样能使3D模型看起来更具立体感。

  • ambient:环境光强度,值0.1表示环境光对整个场景的影响较弱

  • diffuse:漫反射系数,决定光线从表面散射的程度。0.9表示表面具有较强的散射效果,使得表面光照看起来柔和。

  • interpolation:表示启用插值,通常用于在渲染时平滑图像,减少像素化的效果

js 复制代码
  {
    name: 'CT-Bone', 
    gradientOpacity: '4 0 1 255 1',
    specularPower: '10',
    scalarOpacity: '8 -3024 0 -16.4458 0 641.385 0.715686 3071 0.705882',
    specular: '0.2',
    shade: '1',
    ambient: '0.1',
    colorTransfer:
      '16 -3024 0 0 0 -16.4458 0.729412 0.254902 0.301961 641.385 0.905882 0.815686 0.552941 3071 1 1 1',
    diffuse: '0.9',
    interpolation: '1',
  },

在了解完什么是预设后,我们在代码中添加viewport的预设属性(🔑🔑🔑虽然上面洋洋洒洒介绍了这么多有的没的,看的懂看不懂的,但是设置起来仅有一行代码)

js 复制代码
  const viewport = renderingEngine.getViewport(viewportId);
  viewport.setProperties({
    preset: '',
  });

🍇 结束语

至此呢,我们既完成了3D影像的渲染,也顺便更深入的了解了Cornerstone中涉及到的一些概念。虽然我们之前一直用viewport type的枚举值,但是具体有哪些怎么用没有详细了解过,这样可能就会遇到新的场景的时候不能举一反三。本文就这样结束啦,祝各位不会遇到奇奇怪怪的问题、爆掉的内存、无法解析的dicom文件、无法使用的工具, emmm,溜了,溜了~ 👋 👋 👋 👋

配套可运行代码演示:github.com/jianyaoo/vu... clone到本地后直接运行 npm run serve 即可启动,持续更新,欢迎star~

相关推荐
ww大魔王丷7 小时前
python绘制3D瀑布图
开发语言·python·3d
weixin_505154469 小时前
博物馆如何实现3D交互控制展示?
3d·数字孪生·数据可视化·3d产品配置器·3d产品交互展示·3d交互设计工具
refineiks21 小时前
three.js使用3DTilesRendererJS加载3d tiles数据
前端·3d·图形渲染·webgl
hxxjxw21 小时前
python绘制3d建筑
开发语言·python·3d
AiFlutter1 天前
Flutter 使用第三方包加载3d模型
flutter·3d
新拓三维2 天前
DIC技术助力新能源汽车主机厂力学测试研发与整车性能提升
计算机视觉·3d·汽车
jimumeta3 天前
线上VR虚拟展厅里可以展示3D模型么?
3d·vr·虚拟展厅·3d模型·视创云展
Android技术栈3 天前
鸿蒙(API 12 Beta6版)【ArkGraphics 3D场景搭建以及管理】方舟3D图形
3d·华为·harmonyos·鸿蒙·鸿蒙系统·openharmony·图形
Verdure陌矣4 天前
C++项目引入开源库bit7z
开发语言·c++·3d·github
小彭努力中4 天前
9. 相机控件OrbitControls
前端·3d