如何使用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~

相关推荐
CV实验室1 天前
CV论文速递:覆盖视频生成与理解、3D视觉与运动迁移、多模态与跨模态智能、专用场景视觉技术等方向 (11.17-11.21)
人工智能·计算机视觉·3d·论文·音视频·视频生成
Highcharts.js2 天前
使用 Highcharts 3D图表入门
3d·highcharts·使用文档·3d图表·交互图表·三维图表·3d 可视化
O***p6042 天前
C++在游戏中的Ogre3D
游戏·3d·ogre
sdjnled2292 天前
山东裸眼3D立体LED显示屏专业服务商
人工智能·3d
徒慕风流2 天前
GeoSight:基于 Open3D 与 PySide6 的参数化 3D 模型处理与实时点云监控工具
计算机视觉·3d·信号处理
三条猫3 天前
将3D CAD 模型结构树转换为图结构,用于训练CAD AI的思路
人工智能·3d·ai·cad·模型训练·图结构·结构树
二川bro3 天前
第59节:常见问题汇编 - 60个典型问题解答
javascript·3d·threejs
zhangfeng11334 天前
aigc 从2d 到 3d的形式转变,李飞飞在介绍WorldLabs的Marble平台,会围绕“空间智能“的核心理念,自动驾驶就是2d形式
3d·自动驾驶·aigc
裤裤兔4 天前
特定脑区的可视化展示
影像分析·医学影像·影像处理·医学图像·脑科学·大脑·脑影像
da_vinci_x5 天前
PS 3D Viewer (Beta):概念美术的降维打击,白模直接在PS里转光打影出5张大片
人工智能·游戏·3d·prompt·aigc·材质·游戏美术