Cornerstone3D Tools对影像进行交互(上篇)-基础交互工具及同步器

news2024/11/13 9:02:00

⛳️ 前言

在我们日常需求中,除了需要对影像进行可视化展示外,大多数场景下还需要对影像进行调整、注释、分割等操作。Cornerstone3DTools库则支持大多数需要的交互功能。CornerstoneTools支持的工具类型主要分为以下4类:

  • 基础交互类工具:可以在视口中对影像进行操作

  • 注释类工具: 为影像进行注释、测量等操作

  • 分割类工具: 对影像进行分割、标记等操作

  • 同步器工具: 使多个视图进行同步

针对以上4大类型,我们分为上中下3篇文章来展开介绍。上篇则主要对基础交互类工具和同步器工具进行介绍,围绕常用工具的种类、状态及如何注册使用等知识点展开。

🚀 效果演示

点击查看完整代码,欢迎star
在这里插入图片描述

🪜 交互工具

工具组

工具

我们来看一下官网对于工具的定义,工具是至少实现了BaseTool接口的未实例化类。这样看来,一个工具其实就是一个类。我们除了可以使用官网中提供的这些工具之外,我们也可以根据它的定义去自定义一些我们需要的一些工具,关于自定义工具后面会详细说明,在这里我们主要是去介绍它内置的一些工具。如果我们想要使用一个工具的话,首先我们要使用库的顶级addTool函数来添加未实例化的工具,另外需要添加到工具组中。

工具组

以一种简单的方式去定义一个视图/一组工具的表现行为,具有相同工具组的视图将共享工具的配置项、模式等
在这里插入图片描述

常用工具

关于交互类工具,CornerstoneTools主要提供了以下功能, 🔥 标志为常用工具

🔥 PanTool, // 平移工具
🔥 TrackballRotateTool, // 3D旋转工具
🔥 DragProbeTool, // 探针工具
🔥 WindowLevelTool, // 窗宽窗距调整工具
WindowLevelRegionTool, // 窗宽窗距调整工具2
🔥 ZoomTool, // 平移工具
🔥 StackScrollTool, // 鼠标点击及拖动切换层级
🔥 PlanarRotateTool, // 2D旋转工具
🔥 StackScrollMouseWheelTool, // 鼠标滚动切换层级工具
VolumeRotateMouseWheelTool,
MIPJumpToClickTool,

工具状态

在了解完有哪些工具后,我们再来了解一下工具的状态有哪些?

  • Active: 当前工具被激活,可以响应鼠标交互;如果当前工具是注释类工具,在不选中已有的注释时,点击将创建新的注释。

  • Passive: 默认状态,工具非激活状态,不响应交互;如果当前工具是注释类工具,无法创建新的注释,但是如果选中已有注释的话可以拖拽移动。

  • Enabled: 启用状态,不响应交互。如果是注释类或分割类工具,将会渲染已有的操作内容。

  • Disabled: 禁用状态,既不响应交互也不渲染工具

关于操作类工具,我们用到的主要是ActiveDisabled 两个状态,其他两种状态将在中篇注释工具中演示。

使用流程

在了解完基础的概念后,我们来看一下如何在代码中注册并激活工具。

注册工具

// 第一步:向全局状态中添加工具类
addTool(StackScrollMouseWheelTool);
// 第二步:向工具组中添加工具名
const toolGroup = ToolGroupManager.createToolGroup(groupId);
toolGroup.addTool(StackScrollMouseWheelTool.toolName);

// 第三步:将工具组与视图绑定(注意!!:同一时间,一个viewport只能绑定一个ToolGroup)
toolGroup.addViewport(viewportId1, renderingEngineId);

// 第四步:禁用鼠标上下文菜单(如果需要定义右键功能的话)
['element1', 'element2', 'element3'].forEach(id => {
  const dom = document.querySelector(`#${id}`);
  dom.oncontextmenu = () => false;
})

激活工具

关于工具的四种状态,都可以通过setToolxxxx()函数进行设置,以下为设置工具状态为激活状态

// 01 - 获取工具组
const toolGroup = ToolGroupManager.getToolGroup(groupId);

// 02 - 激活工具组的某个工具,并应该与左键【通过设置 mouseButton 属性,设置当前激活的工具是绑定与哪个按键/鼠标键的】
toolGroup.setToolActive(PanTool.toolName, {
   bindings: [{mouseButton: cstEnums.MouseBindings.Primary}],
});

切换工具

通过上面两步就完成了工具的注册与激活,此时就可以直接使用当前激活的工具。但是一个视图中可能有多个工具需要切换,那在切换的时候需要注意以下事项:

  • 当前工具是否已被激活,避免重复激活某个工具

  • 当前键是否有已激活的工具,如果有则禁用掉,避免出现同时激活多个工具而导致的报错问题

const toolGroup = ToolGroupManager.getToolGroup(groupId);

// 第一步:获取当前左键已激活的工具
const activePrimaryToolName = toolGroup.getActivePrimaryMouseButtonTool();

// 第二步:避免重复激活某个工具
if (activePrimaryToolName === toolName) {
  ElMessage({
    message: '当前工具处已于激活状态,点击左键尝试操作',
    type: 'warning',
  })
  return;
}

// 第三步:禁用掉已激活的工具
if (activePrimaryToolName) {
  toolGroup.setToolDisabled(activePrimaryToolName);
}

// 第四步:启用当前选中的工具
toolGroup.setToolActive(toolName, {
  bindings: [{mouseButton: cstEnums.MouseBindings.Primary}],
});

至此,就完成了一套工具的注册、激活、切换的流程,一般我们可以将需要注册的工具作为一个数组或配置项,遍历循环注册添加即可。

🔎 同步器

介绍

我们在使用工具时,可能会遇到在视图A调整缩放或调整窗宽窗位时,在视图B中也要同步响应的需求。这时就需要用到了同步器工具。同步器接受一个源视图、一个目标视图,监听的事件及事件发生在源视图后执行的回调事件。我们使用同步器的目的就是要在多个视图之间进行交互同步,Cornerstone支持自定义同步器,同时也内置了一些常用同步器,本文主要介绍一下内置同步器的使用。

在这里插入图片描述

内置同步器

  • createCameraPositionSynchronizer:相机同步,即两个视图的camera参数同步

  • createVOISynchronizer:窗宽窗位同步,在使用windowLevel工具调整后作为于所有同步视图

  • createZoomPanSynchronizer: 缩放平移同步,使用 ZoomTool/PanTool 工具后作用于所有同步视图

  • createImageSliceSynchronizer: 滚动同步,注意!!!:只能是同三维方向的视图滚动,例如同方向的Stack视图和Volume视图

在这里插入图片描述

使用流程

注册同步器

在cornerstoneTool中内置了以上4种功能的同步器,我们可以直接引入后创建使用

// 第一步:从同步器对象中声明已定义的同步器
const {
  createCameraPositionSynchronizer,
  createVOISynchronizer,
  createZoomPanSynchronizer,
  createImageSliceSynchronizer,
} = synchronizers;


// 第二步:创建需要的同步器实例
createCameraPositionSynchronizer(cameraSynchronizerId); 
createVOISynchronizer(voiSynchronizerId, {
  syncInvertState: false,
});
createZoomPanSynchronizer(zoomSynchronizerId);
createImageSliceSynchronizer(imageSliceSynchronizerId);

添加视图

在创建完同步器后,只需要为同步器添加视图即可实现同步

  • add() 方法表示将当前视图既添加到源视图数组中也添加到目标视图数组中,表现为:当前视图为源视图时(在当前视图进行操作),其他目标视图响应当前视图的操作结果。当前视图为目标视图时(在其他视图上操作时),当前视图相应其他视图的操作结果。作用等同于同时执行 addSourceaddTarget
const synchronizer = SynchronizerManager.getSynchronizer(cameraSynchronizerId);
synchronizer.add({
  renderingEngineId,
  viewportId: viewportId,
});
  • 如果只是想添加视图为源视图(不响应其他视图的交互操作)
synchronizer.addSource({
  renderingEngineId,
  viewportId: viewportId,
});
  • 只添加视图为目标视图(不在当前视图操作)
synchronizer.addTarget({
  renderingEngineId,
  viewportId: viewportId,
});

切换视图

如果想要添加同步视图,使用 add() 函数,但是如果想要删除同步视图,相同参数下使用 remove() 函数

if (toggle) {
  synchronizer.add({
    renderingEngineId,
    viewportId: event.target.value,
  });
} else {
  synchronizer.remove({
    renderingEngineId,
    viewportId: event.target.value,
  });
}

🎉 结束语

至此,我们就介绍完了关于交互工具和同步器的一些基础使用。通过介绍工具的种类、状态和如何去使用一个工具、如何去使用一个同步器等相关内容,完成了上述Demo中的全部功能点的实现。涵盖了日常需求中影像缩放、移动等交互操作、多视图同步等需求场景。文中涉及到的代码已全部更新至 github,欢迎交流讨论 👏👏

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

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

相关文章

VS2022 Cmake项目构建 Qt

一.创建文件和配置CMakeLists 1.创建头文件MainWindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>namespace Ui {class MainWindow; }class MainWindow : public QMainWindow {Q_OBJECTpublic:explicit MainWindow(QWidget* parent nullptr)…

使用Dockerfile创建应用镜像及私有仓库

目录 1.Dockerfile介绍 2.Dockerfile应用 1.创建目录 2.跳转目录 3.编辑启动脚本 4.编辑index.html文件 5.编辑 Dockerfile 6.创建镜像 7.查看镜像 8.创建容器测试 9.挂载其他项目测试 3.私有仓库 1.安装仓库镜像---仓库注册器 2.创建目录 3.启动容器、映射端口、…

读书学习笔记 # Datawhale X 李宏毅苹果书 AI夏令营

文章目录 &#x1f6a9;学习目标&#x1f6a9;学习内容&#x1f6a9; Task1.1&#x1f3af;为什么优化会失败&#x1f4cc;因非信息梯度导致的失败 &#x1f3af;局部极小值与鞍点&#x1f3af;临界点及其种类&#x1f3af;如何判断临界值种类&#x1f4cc;更简便的方法来判断 …

ubuntu环境下部署LNMP集成环境超详细图文教程

ubuntu系统下安装LNMP集成环境 一、Nginx安装 二、安装及配置MySQL数据库 修改密码 三、安装PHP 四、配置Nginx服务 ​编辑五、配置PHP 本文使用的Ubuntu版本为20.04。 php开发中集成环境的安装是必不可少的技能。 而LNMP代表的是&#xff1a;Linux系统下NginxMySQLPHP…

李沐--动手学深度学习 ResNet

1.理论 2.残差块 import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2l#ResNet沿用了VGG完整的3*3卷积层设计.残差块的实现如下&#xff1a; #此代码生成两种类型的网络&#xff1a; #一种是当use_1x1convFalse时&#xff0…

96.SAP MII功能详解(09)Workbench-Transaction Debugging

目录 1.About Transaction Debugging Use Features Activities 2.How to Debug Start Debugging Create Breakpoint Watch Variables Debugging logs 1.About Transaction Debugging Use You use this function to monitor and manipulate a transaction while it …

java框架第一课(mybatis认识)

一.关于mybatis 1.mybatis的背景 mybatis原来 是Apache的一个开源项目iBatis,2010年6月这个项目由ApacheSoftware Foundation 迁移到了 Google Code&#xff0c;并改名为mybatis。 2.mybitis的介绍 (1)MyBatis 是一款优秀的持久层框架(在与数据库交互,数据访问层,数据持久层)。…

深入学习SQL优化的第四天

目录 高级查询与连接 1731 每 位 经 理 的 下 属 员 工 数 量 1789 员 工 的 直 属 部 门 610 判 断 三 角 形 180 连 续 出 现 的 数 字 1164 指 定 日 期 的 产 品 价 格 1204 最 后 一 个 能 进 入 巴 士 的 人 1907 按 分 类 统 计 薪 水 子查询 1978 上…

机器学习入门(Datawhale X 李宏毅苹果书 AI夏令营-Task1)

&#x1f4dd;本文介绍 本文为作者初探机器学习&#xff0c;读苹果书写下的笔记。 &#x1f44b;作者简介&#xff1a;一个正在积极探索的本科生 &#x1f4f1;联系方式&#xff1a;943641266(QQ) &#x1f6aa;Github地址&#xff1a;https://github.com/sankexilianhua &…

AcWing854. Floyd求最短路

注意&#xff1a;Floyd是求图里面任意两个点x&#xff0c;y之间的最短距离 #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N 210, INF 1e9;int n, m, Q; int d[N][N];void floyd() { //枚举1~k个中间节点&a…

书生.浦江大模型实战训练营——(十三)茴香豆:企业级知识库问答工具

最近在学习书生.浦江大模型实战训练营&#xff0c;所有课程都免费&#xff0c;以关卡的形式学习&#xff0c;也比较有意思&#xff0c;提供免费的算力实战&#xff0c;真的很不错&#xff08;无广&#xff09;&#xff01;欢迎大家一起学习&#xff0c;打开LLM探索大门&#xf…

国货之光|暴雨信创服务器亮相北京科博会

8月13-16日&#xff0c;由北京市人民政府主办的第二十六届中国北京国际科技产业博览会&#xff08;简称北京科博会&#xff09;在北京国际会议中心成功举办。作为汇聚全球科技创新成果与智慧交流的高端盛会&#xff0c;北京科博会是推动创新发展成果展示的重要舞台。 青海科技展…

html2canvas ios慎用和createImageBitmap ios慎用

好好好&#xff0c;排查几天&#xff0c;原来是你 小本本记下了[翻白眼][翻白眼][翻白眼] ​html2canvas ios慎用&#xff0c;用了记得设置字体 ​2. createImageBitmap ios慎用&#xff0c;14及以下不兼容&#xff0c;建议更换api

Vue3基础2

1.Hooks 就是进行数据的封装&#xff0c;同一种类型的 数据 方法 计算属性 &#xff0c;放在一起 命名规范 use功能名称.ts 或.js 创建一个文件夹 hooks 1.useDog.ts import { reactive,onMounted } from "vue"; import axios from "axios";export def…

Golang | Leetcode Golang题解之第375题猜数字大小II

题目&#xff1a; 题解&#xff1a; func getMoneyAmount(n int) int {f : make([][]int, n1)for i : range f {f[i] make([]int, n1)}for i : n - 1; i > 1; i-- {for j : i 1; j < n; j {f[i][j] j f[i][j-1]for k : i; k < j; k {cost : k max(f[i][k-1], f[…

Linux命令:创建新的目录的工具mkdir命令详解

目录 一、概述 二、语法 1、基本语法 2、常用选项 3、获取帮助 三、示例 1. 创建单个目录 2. 创建多个目录 3. 使用 -p 选项创建多级目录 4. 设置目录权限 5. 显示创建目录的信息 &#xff08;1&#xff09;一般目录创建 &#xff08;2&#xff09;复杂目录创建 …

大数据技术之Flume 企业开发案例——负载均衡和故障转移(6)

目录 负载均衡和故障转移 1&#xff09;案例需求 2&#xff09;需求分析 3&#xff09;实现步骤 负载均衡和故障转移 1&#xff09;案例需求 使用 Flume1 监控一个端口&#xff0c;其 sink 组中的 sink 分别对接 Flume2 和 Flume3&#xff0c;采用 FailoverSinkProcessor…

裁员后的逆袭:程序员变外卖小哥,AI绘画成就全新职业生涯

一、初代程序员的困境 曾几何时&#xff0c;我是一名初代程序员&#xff0c;投身于互联网行业&#xff0c;为我国信息化建设贡献自己的力量。然而&#xff0c;随着年龄的增长和行业竞争的加剧&#xff0c;我不可避免地遭遇了裁员。面对突如其来的变故&#xff0c;我不得不重新审…

Nginx反向代理B

http协议反向代理 反向代理配置参数 proxy_pass; #用来设置将客户端请求转发给的后端服务器的主机 #可以是主机名(将转发至后端服务做为主机头首部)、IP地址&#xff1a;端口的方式 #也可以代理到预先设置的主机群组&#xff0c;需要模块ngx_http_upstream_module支持 #示例:…

机械学习—零基础学习日志(如何理解概率论9)

大数定律与中心定律 来看一道习题&#xff1a; 这个题目看看&#xff0c;应该是什么呢~下一章来看看解析~ 《概率论与数理统计期末不挂科|考研零基础入门4小时完整版&#xff08;王志超&#xff09;》学习笔记 王志超老师 &#xff08;UP主&#xff09;