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

news2025/6/1 23:21:55

文章目录

  • 前言
  • 一、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视图
				    // 设置默认preset
					viewport.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.coloradmin.cn/o/2393088.html

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

相关文章

2025年渗透测试面试题总结-匿名[校招]高级安全工程师(代码审计安全评估)(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。、 目录 匿名[校招]高级安全工程师(代码审计安全评估) 渗透基础 1. 自我介绍 2. SQL注入写Shell&#xff08;分数…

Jenkins实践(7):Publish over SSH功能

在 Jenkins 中使用Publish over SSH功能,需要安装对应的插件。以下是详细步骤: 1. 安装 Publish over SSH 插件 进入 Jenkins 管理界面 → Manage Jenkins → Manage Plugins。切换到 Available 选项卡,搜索 "Publish Over SSH"。勾选插件并点击 Install without…

SQLite 中文写入失败问题总结

SQLite 中文写入失败问题总结与解决方案 在 Windows 下使用 C 操作 SQLite 数据库时&#xff0c;中文字段经常出现 写入成功但内容显示为 BLOB 或 乱码 的问题。根本原因在于 SQLite 要求字符串以 UTF-8 编码 存储&#xff0c;而默认的 std::string 中文通常是 GB2312/ANSI 编…

ubuntu系统安装Pyside6报错解决

目录 1&#xff0c;问题&#xff1a; 2&#xff0c;解决方法&#xff1a; 2.1 首先查看pypi是否有你需要包的镜像&#xff1a; 2.2 其它方案&#xff1a; 2.3 如果下载很慢&#xff0c;可以换源&#xff1a; 2.4 查看系统架构 Windows Ubuntu 1&#xff0c;问题&#xf…

榕壹云医疗服务系统:基于ThinkPHP+MySQL+UniApp的多门店医疗预约小程序解决方案

在数字化浪潮下,传统医疗服务行业正面临效率提升与客户体验优化的双重挑战。针对口腔、美容、诊所、中医馆、专科医院及康复护理等需要预约或诊断服务的行业,我们开发了一款基于ThinkPHP+MySQL+UniApp的多门店服务预约小程序——榕壹云医疗服务系统。该系统通过模块化设计与开…

苏州SAP代理公司排名:工业园区企业推荐的服务商

目录 一、SAP实施商选择标准体系 1、行业经验维度 2、实施方法论维度 3、资质认证维度 4、团队实力维度 二、SAP苏州实施商工博科技 1、SAP双重认证&#xff0c;高等院校支持 2、以SAP ERP为核心&#xff0c;助力企业数字化转型 三、苏州使用SAP的企业 苏州是中国工业…

数据结构中无向图的邻接矩阵详解

在计算机科学的浩瀚宇宙中&#xff0c;数据结构无疑是那把开启高效编程大门的关键钥匙。对于计算机专业的大学生们来说&#xff0c;数据结构课程是专业学习路上的一座重要里程碑&#xff0c;而其中的图结构更是充满魅力与挑战&#xff0c;像一幅神秘的画卷等待我们去展开。今天…

.NET 7 AOT 使用及 .NET 与 Go 语言互操作详解

.NET 7 AOT 使用及 .NET 与 Go 语言互操作详解 目录 .NET 7 AOT 使用及 .NET 与 Go 语言互操作详解 一、背景与技术概述 1.1 AOT 编译技术简介 1.2 Go 语言与 .NET 的互补性 二、.NET 7 AOT 编译实践 2.1 环境准备 2.2 创建 AOT 项目 2.3 AOT 编译流程 2.4 调试信息处…

OpenCV 第7课 图像处理之平滑(一)

1. 图像噪声 在采集、处理和传输过程中,数字图像可能会受到不同噪声的干扰,从而导致图像质量降低、图像变得模糊、图像特征被淹没,而图像平滑处理就是通过除去噪声来达到图像增强的目的。常见的图像噪声有椒盐噪声、高斯噪声等。 1.1 椒盐噪声 椒盐噪声(Salt-and-pepper N…

React 编译器

&#x1f916; 作者简介&#xff1a;水煮白菜王&#xff0c;一位前端劝退师 &#x1f47b; &#x1f440; 文章专栏&#xff1a; 前端专栏 &#xff0c;记录一下平时在博客写作中&#xff0c;总结出的一些开发技巧和知识归纳总结✍。 感谢支持&#x1f495;&#x1f495;&#…

HCIP:MPLS静态LSP的配置及抓包

目录 一、MPLS的简单的一些知识点 1.MPLS的概述&#xff1a; 2.MPLS工作原理&#xff1a; 3.MPLS的核心组件&#xff1a; 4. MPLS标签 5.MPLS标签的处理 6.MPLS转发的概述&#xff1a; 7.MPLS的静态LSP建立方式 二、MPLS的静态LSP的实验配置 1.配置接口的地址和配置OS…

VASP 教程:VASP 结合 Phonopy 计算硅的比热容

VASP 全称为 Vienna Ab initio Simulation Package&#xff08;The VASP Manual - VASP Wiki&#xff09;是一个计算机程序&#xff0c;用于从第一性原理进行原子尺度材料建模&#xff0c;例如电子结构计算和量子力学分子动力学。 Phonopy&#xff08;Welcome to phonopy — Ph…

[论文阅读]Prompt Injection attack against LLM-integrated Applications

Prompt Injection attack against LLM-integrated Applications [2306.05499] Prompt Injection attack against LLM-integrated Applications 传统提示注入攻击效果差&#xff0c;主要原因在于&#xff1a; 不同的应用对待用户的输入内容不同&#xff0c;有的将其视为问题&a…

DALI DT6与DALI DT8介绍

“DT”全称Device Type&#xff0c;是DALI-2 标准协议中的IEC 62386-102(即为Part 102)部分对不同类型的控制设备进行一个区分。不同的Device Type代表不同特性的控制设备&#xff0c;也代表了这种控制设备拥有的扩展的特性。 在DALI&#xff08;数字可寻址照明接口&#xff09…

day13 leetcode-hot100-24(链表3)

234. 回文链表 - 力扣&#xff08;LeetCode&#xff09; 1.转化法 思路 将链表转化为列表进行比较 复习到的知识 arraylist的长度函数&#xff1a;list.size() 具体代码 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode ne…

图解深度学习 - 基于梯度的优化(梯度下降)

在模型优化过程中&#xff0c;我们曾尝试通过手动调整单个标量系数来观察其对损失值的影响。具体来说&#xff0c;当初始系数为0.3时&#xff0c;损失值为0.5。随后&#xff0c;我们尝试增加系数至0.35&#xff0c;发现损失值上升至0.6&#xff1b;相反&#xff0c;当系数减小至…

MySql--定义表存储引擎、字符集和排序规则

示例&#xff1a; CREATE TABLE users (id INT PRIMARY KEY,name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci,email VARCHAR(100) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci;注意事项&#xff1a; 字符集和排序规则可以按列覆盖表…

优化版本,增加3D 视觉 查看前面的记录

上图先 运来的超出发表上限&#xff0c;重新发。。。 #11:06:57Current_POS_is: X:77Y:471Z:0U:-2 C:\Log\V55.txt import time import tkinter as tk from tkinter import messagebox from PIL import Image, ImageTk import socket import threading from date…

WWW22-可解释推荐|用于推荐的神经符号描述性规则学习

论文来源&#xff1a;WWW 2022 论文链接&#xff1a;https://web.archive.org/web/20220504023001id_/https://dl.acm.org/doi/pdf/10.1145/3485447.3512042 最近读到一篇神经符号集成的论文24年底TOIS的&#xff0c;神经符号集成是人工智能领域中&#xff0c;将符号推理与深…

Linux:shell脚本常用命令

一、设置主机名称 1、查看主机名称 2、用文件的方式更改主机名称 重启后&#xff1a; 3、 通过命令修改主机名 重启后&#xff1a; 二、网络管理命令 1、查看网卡 2、设置网卡 &#xff08;1&#xff09;网卡未被设置过时 &#xff08;2&#xff09;当网卡被设定&#xff0c…