基于cornerstone3D的dicom影像浏览器 第二十四章 显示方位、坐标系、vr轮廓线

06-01 1271阅读

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • 一、工具栏修改
  • 二、切片窗口显示方位文字
    • 1. 修改mprvr.js,添加函数getOrientationMarkers
    • 2. 修改DisplayerArea3D.vue
    • 三、vr窗口显示坐标系
      • 1. 修改mprvr.js 添加OrientationMarkerTool
      • 2. view3d.vue中响应工具栏事件
      • 3. 修改DisplayerArea3D.vue
      • 四、vr窗口显示轮廓线
        • 1. 修改mprvr.js 添加addOutline,showOutline函数
        • 2. view3d.vue中响应工具栏操作
        • 3. 修改DisplayerArea3D.vue
        • 总结

          前言

          vr = volume rendering 体绘制,体渲染

          本章实现三个功能:

          1. mpr窗口中显示方位文字
          2. vr窗口右下角显示坐标系
          3. vr窗口显示轮廓线

            效果如下:

            基于cornerstone3D的dicom影像浏览器 第二十四章 显示方位、坐标系、vr轮廓线


          一、工具栏修改

          • 在工具栏上添加“VR坐标系”、“VR轮廓”、“方位文字” 三个checkbox,用来控制各自的显示与隐藏。添加select选择器用来切换VR坐标系的显示外观(CUBE, AXES, CUSTOM)。 其中CUSTOM的vtp文件点此处下载
            	
            ...
            • 监听以上各元素绑定的变量,发送事件到view3d
              const currentAxes = ref(1);
              const showOutline = ref(true);
              const showAxes = ref(true);
              const showOrientText = ref(true);
              watch(showAxes, (newValue) => {
              	emit("action", { name: "showAxes", value: newValue });
              });
              watch(showOutline, (newValue) => {
              	emit("action", { name: "showOutline", value: newValue });
              });
              watch(showOrientText, (newValue) => {
              	emit("action", { name: "toggleOrientText" });
              });
              watch(currentAxes, (newValue) => {
              	emit("action", { name: "changeAxesType", value: newValue });
              });
              

              二、切片窗口显示方位文字

              计算切片方位文字的算法参考第八章 在Displayer中显示图像方位

              1. 修改mprvr.js,添加函数getOrientationMarkers

              export default class MPR {
              	constructor(params) {
              		this.toolGroup = null;
              		this.vrToolGroup = null;
              		this.renderingEngine = null;
              		this.registered = false;
              		...
              		this.init(params);
              	}
              	init(config = {}) {
              	...
              	}
              	...
              	getOrientationMarkers({ camera, rotation }) {
              		let flipVertical = camera.flipVertical || false;
              		let flipHorizontal = camera.flipHorizontal || false;
              		let newRotation = rotation || 0;
              		let rowCosines, columnCosines;
              		const { viewUp, viewPlaneNormal } = camera;
              		const viewRight = vec3.create();
              		vec3.cross(viewRight, viewUp, viewPlaneNormal);
              		columnCosines = [-viewUp[0], -viewUp[1], -viewUp[2]];
              		rowCosines = viewRight;
              		const rowString = getOrientationStringLPS(rowCosines);
              		const columnString = getOrientationStringLPS(columnCosines);
              		const oppositeRowString = invertOrientationStringLPS(rowString);
              		const oppositeColumnString = invertOrientationStringLPS(columnString);
              		const markers = {
              			top: oppositeColumnString,
              			left: oppositeRowString,
              			right: rowString,
              			bottom: columnString
              		};
              		// If any vertical or horizontal flips are applied, change the orientation strings ahead of
              		// the rotation applications
              		if (flipVertical) {
              			markers.top = invertOrientationStringLPS(markers.top);
              			markers.bottom = invertOrientationStringLPS(markers.bottom);
              		}
              		if (flipHorizontal) {
              			markers.left = invertOrientationStringLPS(markers.left);
              			markers.right = invertOrientationStringLPS(markers.right);
              		}
              		// Swap the labels accordingly if the viewport has been rotated
              		// This could be done in a more complex way for intermediate rotation values (e.g. 45 degrees)
              		if (newRotation === 90 || newRotation === -270) {
              			return {
              				top: markers.left,
              				left: invertOrientationStringLPS(markers.top),
              				right: invertOrientationStringLPS(markers.bottom),
              				bottom: markers.right // left
              			};
              		} else if (newRotation === -90 || newRotation === 270) {
              			return {
              				top: invertOrientationStringLPS(markers.left),
              				left: markers.top,
              				bottom: markers.left,
              				right: markers.bottom
              			};
              		} else if (newRotation === 180 || newRotation === -180) {
              			return {
              				top: invertOrientationStringLPS(markers.top),
              				left: invertOrientationStringLPS(markers.left),
              				bottom: invertOrientationStringLPS(markers.bottom),
              				right: invertOrientationStringLPS(markers.right)
              			};
              		}
              		return markers;
              	}
              }
              

              2. 修改DisplayerArea3D.vue

              • 在mpr 三个div上中、下中、左中、右中添加用于显示方位文字的元素。都与变量showOrientText绑定,用来控制显示/隐藏
                	
                ... {{ axialText.orient.top }} {{ axialText.orient.bottom }} {{ axialText.orient.left }} {{ axialText.orient.right }}
                ...
                ... {{ sagittalText.orient.top }} {{ sagittalText.orient.bottom }} {{ sagittalText.orient.left }} {{ sagittalText.orient.right }}
                ... {{ coronalText.orient.top }} {{ coronalText.orient.bottom }} {{ coronalText.orient.left }} {{ coronalText.orient.right }}
                • 定义三个切片方位文字的保存变量axialText,sagittalText, coronalText
                • 在onMounted中调用MPR bindCameraEvent绑定CAMERA_MODIFIED事件,调用UdpateOrientation函数
                • 添加cameraHandler,UdpateOrientation函数更新方位文字
                  import { ViewportId, getDicomInfo } from "../cornerstone3D/mprvr.js";
                  const cornerText = reactive({
                  	[ViewportId.AXIAL]: {
                  		wwwc: "",
                  		slice: "",
                  		orient: {
                  			top: "",
                  			bottom: "",
                  			left: "",
                  			right: ""
                  		}
                  	},
                  	[ViewportId.SAGITTAL]: {
                  		wwwc: "",
                  		slice: "",
                  		orient: {
                  			top: "",
                  			bottom: "",
                  			left: "",
                  			right: ""
                  		}
                  	},
                  	[ViewportId.CORONAL]: {
                  		wwwc: "",
                  		slice: "",
                  		orient: {
                  			top: "",
                  			bottom: "",
                  			left: "",
                  			right: ""
                  		}
                  	}
                  });
                  const cameraHandler = e => {
                  	UdpateOrientation(e);
                  };
                  const UdpateOrientation = e => {
                  	const { viewportId, camera, rotation} = e.detail;
                  	const markers = theMPR.getOrientationMarkers({ camera, rotation });
                  	if (markers && showOrientText.value) {
                  		cornerText[viewportId].orient = markers;
                  	}
                  };
                  onMounted(() => {
                  	theMPR = new MPR({
                  		elAxial: elAxial.value,
                  		elSagittal: elSagittal.value,
                  		elCoronal: elCoronal.value,
                  		elVR: elVR.value
                  	});
                  	load();
                  	theMPR.bindRenderEvent(renderHandler);
                  	theMPR.bindCameraEvent(cameraHandler);
                  });
                  

                  三、vr窗口显示坐标系

                  1. 修改mprvr.js 添加OrientationMarkerTool

                  • 添加axesConfig 为OrientationMarkerTool定义三种类型外观配置项
                  • 添加工具 this.vrToolGroup.addTool(OrientationMarkerTool.toolName, axesConfig)
                  • 添加showAxes函数,显示/隐藏坐标系
                  • 添加setAxesType函数,切换坐标系外观
                  • loadImages中调用this.showAxes(true),显示默认坐标系-CUBE
                    const {
                    	ToolGroupManager,
                    	Enums: csToolsEnums,
                    	...
                    	OrientationMarkerTool
                    } = cornerstoneTools;
                    const axesConfig = {
                    	orientationWidget: {
                    		viewportSize: 0.08,
                    		minPixelSize: 70,
                    		maxPixelSize: 200
                    	},
                    	overlayMarkerType: OrientationMarkerTool.OVERLAY_MARKER_TYPES.ANNOTATED_CUBE,
                    	overlayConfiguration: {
                    		[OrientationMarkerTool.OVERLAY_MARKER_TYPES.ANNOTATED_CUBE]: {
                    			faceProperties: {
                    				xPlus: {
                    					text: "L",
                    					faceColor: viewportColors[idSagittal], //"#ffff00",
                    					faceRotation: 90
                    				},
                    				xMinus: {
                    					text: "R",
                    					faceColor: viewportColors[idSagittal], //"#ffff00",
                    					faceRotation: 270
                    				},
                    				yPlus: {
                    					text: "P",
                    					faceColor: viewportColors[idCoronal], //"#00ffff",
                    					fontColor: "black",
                    					faceRotation: 180
                    				},
                    				yMinus: {
                    					text: "A",
                    					faceColor: viewportColors[idCoronal], //"#00ffff",
                    					fontColor: "black"
                    				},
                    				zPlus: {
                    					text: "S",
                    					faceColor: viewportColors[idAxial] //"#00ffff",
                    					// fontColor: "white",
                    				},
                    				zMinus: {
                    					text: "I",
                    					faceColor: viewportColors[idAxial] //"#00ffff",
                    					// fontColor: "white",
                    				}
                    			},
                    			defaultStyle: {
                    				fontStyle: "bold",
                    				fontFamily: "Arial",
                    				fontColor: "black",
                    				fontSizeScale: res => res / 2,
                    				faceColor: "#0000ff",
                    				edgeThickness: 0.05,
                    				edgeColor: "black",
                    				resolution: 400
                    			}
                    		},
                    		[OrientationMarkerTool.OVERLAY_MARKER_TYPES.AXES]: {},
                    		[OrientationMarkerTool.OVERLAY_MARKER_TYPES.CUSTOM]: {
                    			polyDataURL: "/src/assets/Human.vtp"
                    		}
                    	}
                    };
                    export default class MPR {
                    	constructor(params) {
                    		this.toolGroup = null;
                    		this.vrToolGroup = null;
                    		this.renderingEngine = null;
                    		this.registered = false;
                    		this.viewportInputArray = null;
                    		this.crosshairsToolActive = true;
                    		this.loaded = false;
                    		this.selecteToolName = "";
                    		this.params = params;
                    		this.volume = null;
                    		this.init(params);
                    	}
                    	init(config = {}) {
                    		const { elAxial, elSagittal, elCoronal, elVR } = config;
                    		cornerstoneTools.addTool(CrosshairsTool);
                    		...
                    		cornerstoneTools.addTool(OrientationMarkerTool);
                    		this.vrToolGroup = ToolGroupManager.getToolGroup(vrToolGroupId);
                    		if (!this.vrToolGroup) {
                    			this.vrToolGroup = ToolGroupManager.createToolGroup(vrToolGroupId);
                    			this.vrToolGroup.addTool(TrackballRotateTool.toolName);
                    			this.vrToolGroup.addTool(ZoomTool.toolName, {
                    				zoomToCenter: true,
                    				invert: true,
                    				minZoomScale: 0.15,
                    				maxZoomScale: 20
                    			});
                    			...
                    			// 添加坐标系工具
                    			this.vrToolGroup.addTool(OrientationMarkerTool.toolName, axesConfig);
                    		}
                    	}
                    	async loadImages(imageIds) {
                    		let newImageIds = [...new Set(imageIds)];
                    		for (let i = 0; i  
                    

                    2. view3d.vue中响应工具栏事件

                    async function OnToolbarAction(action) {
                    	switch (action.name) {
                    		...
                    		case "showOutline":  // 显示/隐藏 轮廓线
                    			displayArea.value.showOutline(action.value);
                    			break;
                    		case "showAxes":  // 显示/隐藏 坐标系
                    			displayArea.value.showAxes(action.value);
                    			break;
                    		case "toggleOrientText":  // 显示/隐藏 切片窗口方位文字
                    			displayArea.value.toggleOrientText();
                    			break;
                    		case "changeAxesType":  // 切换坐标系外观
                    			displayArea.value.changeAxesType(action.value);
                    			break;
                    		default:
                    			break;
                    	}
                    }
                    

                    3. 修改DisplayerArea3D.vue

                    添加并导出工具栏操作响应函数:showAxes,changeAxesType

                    const showAxes = show => {
                    	theMPR.showAxes(show);
                    };
                    const changeAxesType = type => {
                    	theMPR.setAxesType(type);
                    };
                    defineExpose({
                    	...
                    	showAxes,
                    	changeAxesType,
                    });
                    

                    四、vr窗口显示轮廓线

                    1. 修改mprvr.js 添加addOutline,showOutline函数

                    • 导入vtk.js中的vtkOutlineFilter,vtkMapper,vtkActor
                    • 添加addOutline函数,vtkOutlineFilter输入连接this.volume.imageData
                    • 添加showOutline函数,显示/隐藏轮廓线
                    • loadImages中调用this.showOutline(true),默认显示轮廓线
                      import vtkOutlineFilter from "@kitware/vtk.js/Filters/General/OutlineFilter";
                      import vtkMapper from "@kitware/vtk.js/Rendering/Core/Mapper";
                      import vtkActor from "@kitware/vtk.js/Rendering/Core/Actor";
                      let outlineActor = null;
                      export default class MPR {
                      	constructor(params) {
                      		this.toolGroup = null;
                      		this.vrToolGroup = null;
                      		...
                      		this.init(params);
                      	}
                      	init(config = {}) {
                      		...
                      	}
                      	...
                      	addOutline() {
                      		// Create image outline in 3D view
                      		const outline = vtkOutlineFilter.newInstance();
                      		const mapper = vtkMapper.newInstance();
                      		outlineActor = vtkActor.newInstance();
                      		outlineActor.setMapper(mapper);
                      		outline.setInputData(this.volume.imageData);
                      		mapper.setInputData(outline.getOutputData());
                      		const viewport = this.renderingEngine.getViewport(idVolume);
                      		viewport.addActor({ uid: "VOLUME_OUTLINE", actor: outlineActor });
                      		outlineActor.setVisibility(true);
                      		viewport.render();
                      	}
                      	showOutline(show) {
                      		if (!outlineActor) return;
                      		outlineActor.setVisibility(show);
                      		const viewport = this.renderingEngine.getViewport(idVolume);
                      		viewport.render();
                      	}
                      }
                      

                      2. view3d.vue中响应工具栏操作

                      参考第三节

                      3. 修改DisplayerArea3D.vue

                      添加并导出工具栏操作响应函数:showOutline

                      const showOutline = show => {
                      	theMPR.showOutline(show);
                      };
                      defineExpose({
                      	...
                      	showOutline
                      });
                      

                      总结

                      mpr切片窗口显示/隐藏 方位文字。

                      vr窗口显示/隐藏坐标系,切换坐标系外观

                      vr窗口显示/隐藏轮廓线。

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码