当前位置: 首页 > news >正文

基于cornerstone3D的dicom影像浏览器 第二十五章 自定义VR调窗工具

文章目录

  • 前言
  • 一、三维调窗原理
  • 二、自定义三维调窗工具
  • 三、调用流程
    • 1. 修改mprvr.js
    • 2. 修改DispalyerArea3D.vue
    • 3. view3d.vue
    • 4. Toolbar3D.vue
  • 总结


前言

从cornerstoneTools BaseTool派生VolumeShiftColorTool,实现鼠标键按下并移动时,对3D窗口的preset进行偏移,达到三维调窗的目的。
演示视频中绑定鼠标右键进行调窗,和其他工具一样,也可以绑定左键,中键。
效果如下:
在这里插入图片描述


一、三维调窗原理

观察cornerstonejs中 viewport preset 数据结构:
源码位置:packages\core\src\constants\viewportPresets.ts

const presets: ViewportPreset[] = [
{name: 'CT-AAA',gradientOpacity: '4 0 1 255 1',specularPower: '10',scalarOpacity:'12 -3024 0 143.556 0 166.222 0.686275 214.389 0.696078 419.736 0.833333 3071 0.803922',specular: '0.2',shade: '1',ambient: '0.1',colorTransfer:'24 -3024 0 0 0 143.556 0.615686 0.356863 0.184314 166.222 0.882353 0.603922 0.290196 214.389 1 1 1 419.736 1 0.937033 0.954531 3071 0.827451 0.658824 1',diffuse: '0.9',interpolation: '1',},...
]

我们关心两个数据

  1. scalarOpacity:图像灰度值映射不透明度
    值为字符串,以空格为分隔符:
    第一个数据(12)表示有效映射数据个数,即第二个数据(-3024)到最后一个数据(0.803922)的个数。从第二个数据~最后一个数据,每两个数据为一组映射,如第一组[-3024 0],表示像素值为-3024时对应的不透明度为0。第一个数据为12,计算可知有6组映射。
  2. colorTransfer:图像灰度值映射RGB值
    值为字符串,以空格为分隔符:
    第一个数据(24)表示有效映射数据个数,即第二个数据(-3024)到最后一个数据(1)的个数。从第二个数据~最后一个数据,每四个数据为一组映射,如第一组:[-3024 0 0 0],表示像素值为-3024时对应的RGB值 为(0,0,0)。此处为归一化的RGB值,乘255可得RGB值。第一个数据为24,计算可知有6组映射。

实现三维调窗的方法:在鼠标按下并移动时,修改preset中scalarOpacity和colorTransfer中每组映射中的第一个值,即图像灰度值,再把修改后的preset值设置到vieport即可实现。

_shiftVRColor(viewport, preset, pos) {const volumeActor = viewport.getDefaultActor().actor;// 字符串以空格为分割符转为数值数组const color = preset.colorTransfer.split(" ").map(Number);// 偏移数据for (let i = 1; i < color.length; i += 4) {color[i] = color[i] + pos;}// 字符串以空格为分割符转为数值数组const opacity = preset.scalarOpacity.split(" ").map(Number);// 偏移数据for (let i = 1; i < opacity.length; i += 2) {opacity[i] = opacity[i] + pos;}// 生成新的presetconst newPreset = { ...preset };newPreset.colorTransfer = color.join(" ");newPreset.scalarOpacity = opacity.join(" ");// 记录偏移preset.shiftPos = pos;// 应用新的presetcsUtils.applyPreset(volumeActor, newPreset);viewport.render();}

二、自定义三维调窗工具

新建VolumeShiftColorTool.js
参考WindowLevelTool,从BaseTool派生,重写mouseDragCallback。在mouseDragCallback中调用上一节的_shiftVRColor函数
源码位置:packages\tools\src\tools\WindowLevelTool.ts

import {getEnabledElement,utilities as csUtils,VolumeViewport3D
} from "@cornerstonejs/core";
import * as cornerstoneTools from "@cornerstonejs/tools";
const { BaseTool } = cornerstoneTools;export default class VolumeShiftColorTool extends BaseTool {static toolName;constructor(toolProps = {},defaultToolProps = {supportedInteractionTypes: ["Mouse", "Touch"]}) {super(toolProps, defaultToolProps);}touchDragCallback(evt) {this.mouseDragCallback(evt);}mouseDragCallback(evt) {const { element, deltaPoints } = evt.detail;const enabledElement = getEnabledElement(element);const { viewport } = enabledElement;if (viewport instanceof VolumeViewport3D) {const { preset } = viewport.getProperties();let shiftPos = preset.shiftPos || 0;// 鼠标上下移动const yDelta = deltaPoints.canvas[1];shiftPos += yDelta;this._shiftVRColor(viewport, preset, shiftPos);}}_shiftVRColor(viewport, preset, pos) {const volumeActor = viewport.getDefaultActor().actor;const color = preset.colorTransfer.split(" ").map(Number);for (let i = 1; i < color.length; i += 4) {color[i] = color[i] + pos;}const opacity = preset.scalarOpacity.split(" ").map(Number);for (let i = 1; i < opacity.length; i += 2) {opacity[i] = opacity[i] + pos;}const newPreset = { ...preset };newPreset.colorTransfer = color.join(" ");newPreset.scalarOpacity = opacity.join(" ");preset.shiftPos = pos;csUtils.applyPreset(volumeActor, newPreset);viewport.render();}
}VolumeShiftColorTool.toolName = "VolumeShiftColor";

三、调用流程

1. 修改mprvr.js

  • 导入、添加VolumeShiftColorTool
  • 添加函数enableVolumeShiftColor,切换ZoomTool和VolumeShiftColorTool绑定鼠标右键
import VolumeShiftColorTool from "./VolumeShiftColorTool";export default class MPR {constructor(params) {this.toolGroup = null;this.vrToolGroup = null;this.renderingEngine = null;this.registered = false;...this.init(params);}init(config = {}) {const { elAxial, elSagittal, elCoronal, elVR } = config;cornerstoneTools.addTool(CrosshairsTool);...this.vrToolGroup = ToolGroupManager.getToolGroup(vrToolGroupId);cornerstoneTools.addTool(VolumeShiftColorTool);if (!this.vrToolGroup) {...this.vrToolGroup.addTool(VolumeShiftColorTool.toolName);}}enableVolumeShiftColor(enable) {if (enable) {this.vrToolGroup.setToolDisabled(ZoomTool.toolName);this.vrToolGroup.setToolActive(VolumeShiftColorTool.toolName, {bindings: [{mouseButton: MouseBindings.Secondary // Right Click}]});} else {this.vrToolGroup.setToolDisabled(VolumeShiftColorTool.toolName);this.vrToolGroup.setToolActive(ZoomTool.toolName, {bindings: [{mouseButton: MouseBindings.Secondary // Right Click}]});}}
}

2. 修改DispalyerArea3D.vue

const enableVRShiftColor = enable => {theMPR.enableVolumeShiftColor(enable);
};defineExpose({...enableVRShiftColor
});

3. view3d.vue

响应工具栏enableVRShift事件

async function OnToolbarAction(action) {switch (action.name) {...case "enableVRShift":displayArea.value.enableVRShiftColor(action.value);break;default:break;}
}

4. Toolbar3D.vue

添加“VR调窗” el-checkbox, 绑定变量enableVRShift

const enableVRShift = ref(false);
watch(enableVRShift, (newValue) => {emit("action", { name: "enableVRShift", value: newValue });
});<template><div class="toolbar">...<div class="toolbar-row"><el-checkbox v-model="enableVRShift" label="VR调窗" size="large" /></div>...</div>
</template>

总结

  1. 讲解三维调窗原理
  2. 自定义工具流程

相关文章:

  • 基于正点原子阿波罗F429开发板的LWIP应用(4)——HTTP Server功能
  • 杰发科技AC7840——CSE硬件加密模块使用(2)
  • JS中的属性描述符
  • OpenCV CUDA模块直方图计算------用于在 GPU 上执行对比度受限的自适应直方图均衡类cv::cuda::CLAHE
  • 浅谈 JavaScript 性能优化
  • Linux——数据链路层
  • 实验三 企业网络搭建及应用
  • 2025吉林ccpc【部分题解】
  • Appium+python自动化(七)- 认识Appium- 上
  • Rust: CString、CStr和String、str
  • Git典型使用场景相关命令
  • react diff 算法
  • 基于Qt的MCP LLM代理服务开发实战:从0到1扩展大语言模型
  • React从基础入门到高级实战:React 生态与工具 - 探索 React 生态中的工具和库:提升开发效率与项目质量
  • 前端面经 React 组件常见的声明方式
  • 征程 6X VDSP 调试方法
  • macOS 风格番茄计时器:设计与实现详解
  • 4.8.1 利用Spark SQL实现词频统计
  • mp中的密码处理
  • 设计模式-依赖倒转原则
  • 企业只有建立自己的网站平台/刚刚刚刚刚刚刚刚刚刚刚刚刚刚刚
  • 宁波seo自然优化技术/百度首页优化排名
  • 私人兼职做网站开发/百度点击器找名风
  • nas 建网站/林哥seo
  • 做盗版小说网站赚钱嘛/比较成功的网络营销案例
  • web网站设计的要求/推广关键词外包