基于cornerstone3D的dicom影像浏览器 第二十七章 设置vr相机,复位视图

article/2025/7/15 17:20:12

文章目录

  • 前言
  • 一、VR视图设置相机位置
    • 1. 相机位置参数
    • 2. 修改mprvr.js
    • 3. 调用流程
      • 1) 修改Toolbar3D.vue
      • 2) 修改View3d.vue
      • 3) 修改DisplayerArea3D.vue
  • 二、所有视图复位
    • 1.复位流程说明
    • 2. 调用流程
      • 1) Toolbar3D中添加"复位"按钮,发送reset事件
      • 2) View3d.vue中响应reset事件,调用DispalerArea3D中的reset函数
      • 3) DisplayerArea3D中添加并导出reset函数,增加setDefaultWindow函数
  • 总结


前言

  1. VR窗口通过设置相机显示“前视( A )”、“后视( P )”、“左视( L )”、“右视( R )”、“俯视( S )”、“仰视( I )” 图像
  2. 实现各视图复位功能
    效果如下:
    在这里插入图片描述

一、VR视图设置相机位置

1. 相机位置参数

vtk坐标系,以人体为例:
x 轴正向: 从右至左 [1,0,0],反向:从左至右[-1,0,0]
y轴正向:从前至后[0,1,0],反向:从后至前[0,-1,0]
z轴正向:从下至上[0,0,1],反向:从上至下[0,0,-1]
相机的两个参数:

  1. viewPlaneNormal,视平面法向量,与视线相反的方向。如相机对着物体拍摄,从物体指向相机镜头的方向就是视平面法向量。
  2. viewUp,相机向上的方向

于是可得以下参数:
前视( A ): viewPlaneNormal即为y轴反向[0, -1, 0],viewUp z轴正向[0,0,1]
后视( P ): viewPlaneNormal即为y轴正向[0, 1, 0],viewUp z轴正向[0,0,1]
左视( L ): viewPlaneNormal即为x轴正向[1, 0, 0],viewUp z轴正向[0,0,1]
右视( R ): viewPlaneNormal即为x轴反向[-1, 0, 0],viewUp z轴正向[0,0,1]
俯视( S ): viewPlaneNormal即为z轴正向[0, 0, 1],viewUp y轴正向[0,1,0]或反向[0,-1,0]
仰视( I ): viewPlaneNormal即为z轴反向[0, 0, -1],viewUp y轴反向[0,-1,0]

2. 修改mprvr.js

  1. 获取viewport camera
  2. 设置camera两个参数viewPlaneNormal、viewUp
  3. 调用viewport.resetCamera()应用生效
const cameraPos = {A: {viewPlaneNormal: [0, -1, 0],viewUp: [0, 0, 1]},P: {viewPlaneNormal: [0, 1, 0],viewUp: [0, 0, 1]},L: {viewPlaneNormal: [1, 0, 0],viewUp: [0, 0, 1]},R: {viewPlaneNormal: [-1, 0, 0],viewUp: [0, 0, 1]},S: {viewPlaneNormal: [0, 0, 1],viewUp: [0, 1, 0]},I: {viewPlaneNormal: [0, 0, -1],viewUp: [0, -1, 0]}
};export default class MPR {...setCameraPosition(position) {// 获取相机位置参数const data = cameraPos[position];const viewport = this.renderingEngine.getViewport(idVolume);// 设置相机位置参数viewport.setCamera({viewUp: data.viewUp,viewPlaneNormal: data.viewPlaneNormal});viewport.resetCamera();}
}

3. 调用流程

1) 修改Toolbar3D.vue

  • 添加操作元素el-select
  • 绑定变量currentCameraPos
  • 监听currentCameraPos变化,发送changeCameraPos事件
<script setup name="Toolbar3D">
const cameraPos = [{name:"前视(A)", value: "A"},{name:"后视(P)", value: "P"},{name:"左视(L)", value: "L"},{name:"右视(R)", value: "R"},{name:"俯视(S)", value: "S"},{name:"仰视(I)", value: "I"},
];
const currentCameraPos = ref("A");
watch(currentCameraPos, (newValue) => {emit("action", { name: "changeCameraPos", value: newValue });
});
</script>
<template>...<div class="toolbar-row"><div class="pre-label">Camera:</div><el-select v-model="currentCameraPos" placeholder="Select Camera Position" style="width: 200px"><el-option v-for="item in cameraPos" :key="item.value" :label="item.name" :value="item.value" /></el-select></div>
</template>

2) 修改View3d.vue

在OnToolbarAction中添加事件响应

async function OnToolbarAction(action) {...case "changeCameraPos":displayArea.value.setCameraPosition(action.value);break;
}

3) 修改DisplayerArea3D.vue

添加并导出函数setCameraPosition

const setCameraPosition = position => {theMPR.setCameraPosition(position);
};defineExpose({...setCameraPosition
});

二、所有视图复位

1.复位流程说明

VR视图:

  1. 图像加载成功后保存相机初始参数
  2. 相机参数设置为初始参数
  3. 设置默认preset

切片视图:
3. 调用viewport.resetCamera()
4. 设置默认窗宽窗位

修改mprvr.js,在loadImages函数中保存相机初始参数。增加resetCamera函数

const initVolumeCamera = {viewUp: [],viewPlaneNormal: [],position: [],focalPoint: [],viewAngle: 0,parallelScale: 1
};export default class MPR {...async loadImages(imageIds) {...this.renderingEngine.renderViewports(viewportIds);const viewport = this.renderingEngine.getViewport(idVolume);await setVolumesForViewports(this.renderingEngine, [{ volumeId }], [idVolume]).then(() => {viewport.setProperties({preset: "CT-Coronary-Arteries-2"});// 保存相机初始参数const camera = viewport.getCamera();initVolumeCamera.viewUp = camera.viewUp;initVolumeCamera.viewPlaneNormal = camera.viewPlaneNormal;initVolumeCamera.position = camera.position;initVolumeCamera.focalPoint = camera.focalPoint;initVolumeCamera.viewAngle = camera.viewAngle;initVolumeCamera.parallelScale = camera.parallelScale;});...}resetCamera() {if (!this.loaded) return;viewportIds.forEach(viewportId => {const viewport = this.renderingEngine.getViewport(viewportId);if (viewport) {if (viewportId === idVolume) { // VR视图// 设置默认presetviewport.setProperties({preset: "CT-Coronary-Arteries-2"});// 设置初始相机参数const camera = viewport.getCamera();camera.viewUp = initVolumeCamera.viewUp;camera.viewPlaneNormal = initVolumeCamera.viewPlaneNormal;camera.position = initVolumeCamera.position;camera.focalPoint = initVolumeCamera.focalPoint;camera.viewAngle = initVolumeCamera.viewAngle;camera.parallelScale = initVolumeCamera.parallelScale;viewport.setCamera(camera);} else { // 切片视图viewport.resetCamera();viewport.render();}}});}
}

2. 调用流程

1) Toolbar3D中添加"复位"按钮,发送reset事件

2) View3d.vue中响应reset事件,调用DispalerArea3D中的reset函数

3) DisplayerArea3D中添加并导出reset函数,增加setDefaultWindow函数

// defWW, defWL在load函数中保存了默认窗值
const setDefaultWindow = () => {theMPR.setWindow(defWW.value, defWL.value);
};const reset = () => {theMPR.resetCamera();setDefaultWindow();
};defineExpose({...reset 
});

总结

1.讲解VR视图六个正向视图的相机参数是如何设置的
2.VR视图与切片视图复位


http://www.hkcw.cn/article/osokybSIrt.shtml

相关文章

以色列防长:哈马斯要么接受美方提案 要么面临毁灭

当地时间5月30日,以色列国防部长卡茨通过其个人社交媒体账号发表声明称,在以军强大的军事压力之下,巴勒斯坦伊斯兰抵抗运动(哈马斯)将被迫接受选择:接受美方提出加沙停火提案,或者被以色列消灭。△以色列国防部长卡茨(资料图)卡茨在声明中表示,当前以军正全力在加沙地…

古巴外交部召见美国临时代办 抗议其无礼行为

△古巴哈瓦那(资料图)当时间5月30日,古巴外交部召见了美国驻古巴临时代办迈克哈默(Mike Hammer)并表示,迈克哈默自2024年11月抵达古巴以来,对古巴表现出的不友好行为,既不符合他外交官的身份,也表现了对古巴人民的不尊重。古巴外交部美国双边事务总司主任加西亚向迈克…

Java处理动态的属性:字段不固定、需要动态扩展的 JSON 数据结构

引言 应用场景: 签名测试接口、表单配置项、参数列表、插件信息等。技术实现:JSONObject 接收、使用json格式的字符串,或者@JsonAnySetter/@JsonAnyGetter注解方法来处理动态的属性。I JSONObject 接收和返回 例子:表单配置 接口对应的表单配置信息 JSONObject 接收和返回…

leetcode1201. 丑数 III -medium

1 题目&#xff1a;1201. 丑数 III. 官方标定难度&#xff1a;中 丑数是可以被 a 或 b 或 c 整除的 正整数 。 给你四个整数&#xff1a;n 、a 、b 、c &#xff0c;请你设计一个算法来找出第 n 个丑数。 示例 1&#xff1a; 输入&#xff1a;n 3, a 2, b 3, c 5 输出…

【Oracle】DML语言

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. DML概述1.1 什么是DML&#xff1f;1.2 DML的核心功能 2. INSERT语句详解2.1 基础插入操作2.2 子查询插入2.3 多表插入2.4 批量插入优化 3. UPDATE语句详解3.1 基础更新操作3.2 关联更新3.3 批量更新优化 4. …

安装启动Mosquitto以及问题error: cjson/cJSON.h: No such file or directory解决

安装Mosquitto 在官方下载地址&#xff1a;https://mosquitto.org/files/source/ 选择版本下载 安装环境是linux centos7&#xff0c;上传 mosquitto-2.0.18.tar.gz 文件到 /mqtt 文件夹下 tar -xvf mosquitto-2.0.18.tar.gz #解压 cd mosquitto-2.0.18/ #切换到解压目录下…

附件上传唯一性校验

1. Overridepublic String uploadFile(MultipartFile file, String id, String funNo, String ctType) {//TODO 附件重复判断// 计算文件哈希值// 将MultipartFile转换为临时File对象String fileHash "";try {File tempFile convertMultipartFileToFile(file);// …

正点原子AU15开发板!板载40G QSFP、PCIe3.0x8和FMC LPC等接口,性能强悍!

正点原子AU15开发板&#xff01;板载40G QSFP、PCIe3.0x8和FMC LPC等接口&#xff0c;性能强悍&#xff01; 正点原子AU15开发板搭载Xilinx Artix UltraScale 系列FPGA&#xff0c;核心板主控芯片的型号是XCAU15P-FFVB676-2I。开发板由核心板&#xff0b;底板组成&#xff0c;外…

Attention-> flashAttention材料参考

1、 一文看懂 Attention&#xff08;本质原理3大优点5大类型&#xff09;_attention结构-CSDN博客2​​​​​​​2https://blog.csdn.net/haima1998/article/details/107845549 2、 一文看懂 NLP 里的模型框架 Encoder-Decoder 和 Seq2Seq (easyai.tech) 3、 详解深度学习…

MySQL高可用集群

https://dev.mysql.com/doc/mysql-shell/8.4/en/mysql-innodb-cluster.html 1 什么是MySQL高可用集群 MySQL高可用集群&#xff1a;MySQL InnoDB ClusterInnoDB Cluster是MySQL官方实现高可用读写分离的架构方案&#xff0c;包含以下组件 MySQL Group Replication&#xff1a;简…

山洪灾害声光电监测预警解决方案

一、方案背景 我国是一个多山的国家&#xff0c;山丘区面积约占国土面积的三分之二。每年汛期&#xff0c;受暴雨等因素影响&#xff0c;极易引发山洪和泥石流。山洪、泥石流地质灾害具有突发性、流速快、流量大、物质容量大和破坏力强等特点&#xff0c;一旦发生&#xff0c;将…

2025年最新工程项目管理系统应该具备哪些模块?

随着数字化转型浪潮席卷工程行业&#xff0c;工程项目管理系统的作用愈发凸显。2025年&#xff0c;工程项目管理系统的核心目标不仅是提升项目效率&#xff0c;更在于通过智能化、集成化技术实现全生命周期的精细化管理。基于行业趋势和企业实际需求&#xff0c;结合金众诚工程…

unity入门:同一文本不同颜色显示

unity入门&#xff1a;同一文本不同颜色显示 同一文本不同颜色显示#RRGGBBAA&#xff08;带透明度&#xff09;用法 同一文本不同颜色显示 在Unity中&#xff0c;如果想让文本中的某一部分显示不同的颜色&#xff0c;可以使用富文本(Rich Text)标记&#xff0c;在字符串中插入…

128、STM32H723ZGT6实现串口IAP

Bootloader程序通过串口接收*.bin文件数据&#xff0c;写入到内部flash区域&#xff0c;然后跳转APP应用程序 flash读写数据参考我的博客&#xff1a;127、stm32h743XI内部flash 注意&#xff1a;H723系列flash必须32字节写入&#xff0c;并且擦除时别重启|断电&#xff0c;不然…

【Netty系列】Reactor 模式 2

目录 流程图说明 关键流程 以下是 Reactor 模式流程图&#xff0c;结合 Netty 的主从多线程模型&#xff0c;帮助你直观理解事件驱动和线程分工&#xff1a; 流程图说明 Clients&#xff08;客户端&#xff09; 多个客户端&#xff08;Client 1~N&#xff09;向服务端发起连…

接口自动化测试用例的编写方法

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 phpunit 接口自动化测试系列 Post接口自动化测试用例 Post方式的接口是上传接口&#xff0c;需要对接口头部进行封装&#xff0c;所以没有办法在浏览器下直接调…

2025030给荣品PRO-RK3566开发板单独升级Android13的boot.img

./build.sh init ./build.sh -K ./build.sh kernel 【导入配置文件】 Z:\Android13.0\rockdev\Image-rk3566_t\config.cfg 【更新的内核】 Z:\Android13.0\rockdev\Image-rk3566_t\boot.img 【导入分区表&#xff0c;使用原始的config.cfg会出错的^_】 Z:\Android13.0\rockdev\…

伊拉克军方打死6名“伊斯兰国”武装分子

△伊拉克联合行动指挥部发布视频截图当地时间5月30日,伊拉克联合行动指挥部下属安全媒体中心发表声明称,29日晚至30日早间,伊军方出动战机对位于该国北部萨拉赫丁省沙伊谷地的极端组织“伊斯兰国”武装分子藏匿点发动空袭,打死了6名武装分子,并摧毁其藏匿点。(总台记者 米…

Python打卡训练营Day40

DAY 40 训练和测试的规范写法 知识点回顾&#xff1a; 彩色和灰度图片测试和训练的规范写法&#xff1a;封装在函数中展平操作&#xff1a;除第一个维度batchsize外全部展平dropout操作&#xff1a;训练阶段随机丢弃神经元&#xff0c;测试阶段eval模式关闭dropout 作业&#x…

Haproxy搭建web群集

目录 一&#xff1a;Haproxy 1.Haproxy常见的调度算法 二&#xff1a;环境案例 1.配置web主机 2.配置haproxy主机 3.Haproxy日志 一&#xff1a;Haproxy Haproxy 是目前比较流行的一种群集调度工具&#xff0c;同类群集调度工具有很多,如 LVS 和 Nginx。相比较而言&#…