如何使用cornerstone3D渲染3D影像

🍓 前言

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

🥑 效果演示

点击查看完整代码

在这里插入图片描述

🍒 实现及概念

代码实现

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

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视图的形式展示

  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影像。

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:表示启用插值,通常用于在渲染时平滑图像,减少像素化的效果

  {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的预设属性(🔑🔑🔑虽然上面洋洋洒洒介绍了这么多有的没的,看的懂看不懂的,但是设置起来仅有一行代码)

  const viewport = renderingEngine.getViewport(viewportId);viewport.setProperties({preset: '',});

🍇 结束语

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/52292.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详细分析 el-progress的基本知识以及用法(附Demo)

目录 前言1. 基本知识2. Demo3. 实战 前言 由于实战项目中有所引用,对此记录基本的知识点,并且以Demo的形式呈现 1. 基本知识 el-progress 是 Element Plus UI 库中的一个进度条组件,用于显示任务的完成情况 可以帮助用户了解某个操作或任…

移动云电脑手机端3.0全新升级,畅享个人便捷管理,筑牢安全管控防线

在当今数字化飞速发展的时代,企业对于高效、便捷且安全的办公模式需求日益迫切。移动云电脑手机端3.0全新升级,迎来科技领域的又一突破。其基于企业管理平台为企业客户提供管理能力,实现对用户、终端、资源的全方位集中管控,助力提…

探索GitLab:从搭建到高效使用的实用指南

企业里为什么喜欢使用GitLab 一、GitLab简介二、搭建GitLab三、GitLab的权限管理3.1、用户注册3.2、创建用户组3.3、为用户组添加用户3.4、为工程添加访问权限 四、GitLab的code review五、团队知识管理六、总结 一、GitLab简介 GitLab是利用 Ruby on Rails 一个开源的版本管理…

Go开发桌面客户端软件小试:网站Sitemap生成

在前一篇【手把手教你用Go开发客户端软件(使用Go HTML)】中,我们详细介绍了如何通过Go语言开发一个简单的桌面客户端软件。本次,我们将继续这个系列,使用Go语言结合Sciter的Go绑定库——go-sciter,实战开发…

Linux虚拟机磁盘管理-新分区磁盘挂载

挂载mount 注意:挂载前一定要对磁盘进行文件系统创建,否则无法挂载磁盘 比如mkfs.ext4系统文件 磁盘挂载前和挂载后: linux系统重启后磁盘挂载没有了怎么办(不建议,哪怕输错一个字系统起不来,自己操作的时候出现过起不…

大语言模型-PDF文档解析

PDF解析能够提升大语言模型系统的信息处理能力和应用范围,为用户提供更加便捷、高效、个性化的服务体验。本文介绍三种常用的pdf解析方式:Open Parse、pdfplumber、PyMuPD。 一、Open Parse Open Parse是一个能够直观地识别文档布局并有效地对其进行分…

Qt 系统相关 - 网络与音视频

目录 一、Qt 网络 1. UDP Socket 1.1 核心 API 概览 1.2 回显服务器 1.3 回显客户端 2. TCP Socket 2.1 核心 API 概览 2.2 回显服务器 2.3 回显客户端 3. HTTP Client 3.1 核心 API 3.2 代码示例 二、Qt 音视频 1. Qt 音频 1.1 核心API概览 1.2 示例 2. Qt 视…

加速网络体验,Squid缓存代理:让浏览如飞,畅享无限网络速度!

作者简介:我是团团儿,是一名专注于云计算领域的专业创作者,感谢大家的关注 座右铭: 云端筑梦,数据为翼,探索无限可能,引领云计算新纪元 个人主页:团儿.-CSDN博客 目录 前言: squ…

订单到期关闭如何实现?

目录 一、被动关闭 二、定时任务 三、JDK自带的DelayQueue 四、Netty的时间轮 五、Kafka的时间轮 六、RocketMQ延迟消息 七、RabbitMQ死信队列 八、RabbitMQ插件 九、Redis过期监听 十、Redis的Zset 十一、Redisson 在电商、支付等系统中,一般都是先创建…

详解华为项目管理,附华为高级项目管理内训材料

(一)华为在项目管理中通过有效的沟通、灵活的组织结构、坚持不懈的努力、细致的管理和科学的考核体系,实现了持续的创新和发展。通过引进先进的管理模式,强调以客户需求为导向,华为不仅优化了技术管理和项目研发流程&a…

多重示例详细说明Eureka原理实践

Eureka原理(Eureka Principle)是指在长时间的思考和积累之后,通过偶然的瞬间获得灵感或发现解决问题的方法的一种认知现象。这个过程通常包括三个主要阶段:准备阶段、潜伏期以及突然的灵感爆发。下面详细说明Eureka原理的实践步骤…

vue3 组合式API

<!-- 深度监听 deep 点击按钮控制台&#xff0c;才输出count变化了: 1, 老值: 0;否则控制台不输出 --> <script setup>import { ref,watch } from vueconst state ref({count:0})const setCount () > {state.count.value}watch(state, () > {console.log(…

QT中通过TCP协议多线程的文件传输(客户端)

首先&#xff0c;新建一个项目&#xff0c;我命名为了SendFileClient 首先我们要在pro文件中 代码第一行加入network的后缀 一、窗口搭建 如图所示&#xff0c;在第一个QWidget中让客户端输入IP&#xff0c;端口号 连接服务器 第二个Qwidget 设置一个LineEdit,供客户端选择要…

[godot] 采用状态机时,如何处理攻击时移动?如“冲撞”

这里以‘史莱姆撞击’为例子&#xff0c;将‘空中跃进’定义为伤害帧。&#xff08;见下图&#xff09; 先梳理流程&#xff1a;a.史莱姆原地蓄力(起跳准备)--->b.跳起并移动一段距离(空中跃进)--->c.落地调整 一 当状态机进入‘攻击状态’时&#xff0c;在enter()中…

计算机毕业设计PySpark+Django农产品推荐系统 农产品爬虫 农产品商城 农产品大数据 农产品数据分析可视化 PySpark Hadoop

基于Spark的农产品个性推荐系统 相关技术介绍: 1. Python Python是一种高级编程语言&#xff0c;具有简洁、易读、易学的特点&#xff0c;被广泛应用于Web开发、数据分析、人工智能等领域。 在此系统中&#xff0c;我们使用Python进行后端开发&#xff0c;利用其强大的语法…

基本数据类型 --- 浮点型

float的机器码表示&#xff1a; 一个float数据 (pow(-1, sign) fraction) * pow(2, exponent - 127) 由上图&#xff0c;可得&#xff1a; (pow(-1, sign) fraction) * pow(2, exponent - 127) ( 1 2^(-2) ) * pow(2, 124-127) 0.15625 其他文章&#xff1a; https://b…

鸿蒙HarmonyOS之使用ArkTs语言实现层级树状目录选择UI

一、实现效果 二、实现步骤 代码示例中用到的颜色、图片等资源可以自行替换设置 1、Index.ets 里面调用 import { CategoryView} from ./CategoryView;//主页面 Entry Component struct Index {State tabsIndex: number 0;build() {...//层级目录ViewCategoryView()...} …

ReTagList标签列表(API)

组件实现基于 Vue3 + Element Plus + Typescript,同时引用 vueUse + lodash-es + tailwindCss (不影响功能,可忽略) 基于ElTag实现的Tag列表,支持Tag列表多选,动态Tag列表 ReTagList标签列表 基础 简单展示Tag列表,可通过size指定尺寸 查看 /demo/tag-list/basic.md …

Arduino开源四足蜘蛛机器人制作教程

视频教程&#xff1a;手把手叫你做四足蜘蛛机器人——1零件介绍_哔哩哔哩_bilibili 一、项目介绍 1.1 项目介绍 Arduino主控&#xff0c;图形化编程&#xff0c;趣味学习 Arduino nano开发板舵机扩展底板 4.8V可充电电池&#xff0c;支持Arduino C语言编程和米思齐图形化编程…