基于cornerstone3D的dicom影像浏览器 第五章 在Displayer四个角落显示信息

先看效果

dicom四个角落显示信息

1.在displayer.vue文件中引入对应的依赖

复制代码
import { vec3 } from "gl-matrix";
import {
  RenderingEngine,
  getRenderingEngine,
  Enums,
  utilities as csUtils,
} from "@cornerstonejs/core";
const { IMAGE_RENDERED, CAMERA_MODIFIED } = Enums.Events;
import { utilities } from "@cornerstonejs/tools";
const { getOrientationStringLPS, invertOrientationStringLPS } =
  utilities.orientation;

2.监听事件

复制代码
mounted() {
    ...

    this.$refs.displayer.addEventListener(IMAGE_RENDERED, this.onImageRendered);
    this.$refs.displayer.addEventListener(
      CAMERA_MODIFIED,
      this.onCameraModified
    );
    ...
  },

3.相关函数

复制代码
methods:{

    onImageRendered() {
      if (!this.state.series) return;
      this.drawText();
    },
    onCameraModified(event) {
      if (!this.state.series) return;
      const markers = this.getOrientationMarkers({
        image: this.state.image,
        camera: event.detail.camera,
        rotation: event.detail.rotation,
      });
      this.orientation.top = markers.top;
      this.orientation.bottom = markers.bottom;
      this.orientation.left = markers.left;
      this.orientation.right = markers.right;
    },
    drawText() {
      const canvas = this.$refs.displayer.querySelector(".cornerstone-canvas");
      const context = canvas.getContext("2d");
      const cvs_w = canvas.clientWidth;
      const cvs_h = canvas.clientHeight;

      const mtx = context.getTransform();
      context.resetTransform();

      context.font = "14px Arial";
      context.fillStyle = "white";
      context.textAlign = "left";
      context.textBaseline = "top";

      const idx = this.state.viewport.getCurrentImageIdIndex();

      const imageId = this.state.imageIds[idx];
      const image = this.state.series.GetImageById(imageId);

      let x = 5;
      let y = 5;
      let h = 17;
      let val;

      // 左上角 left-top
      // 姓名
      val = image.PatientName;
      context.fillText(val, x, y);
      y += h;
      // PatientId
      val = image.PatientID;
      context.fillText(val, x, y);
      y += h;
      // 年龄(或者生日)+性别
      val = image.AgeAndSex;
      if (val) {
        context.fillText(val, x, y);
        y += h;
      }
      // Image Comments
      val = image.ImageComments;
      if (val) {
        context.fillText(val, x, y);
        y += h;
      }

      // 左下角 left-bottom
      y = cvs_h - h;
      // 医院名
      val = image.HospitalName;
      if (val) {
        context.fillText(val, x, y);
        y -= h;
      }
      // 图像时间
      val = image.ContentDate + " " + image.ContentTime;
      if (val) {
        context.fillText(val, x, y);
        y -= h;
      }
      // Study Description
      val = image.StudyDesc;
      if (val) {
        context.fillText(val, x, y);
        y -= h;
      }
      //series Description
      val = image.SeriesDesc;
      if (val) {
        context.fillText(val, x, y);
        y -= h;
      }
      //患者方向
      val = image.PatientPosition;
      if (val) {
        context.fillText(val, x, y);
        y -= h;
      }

      // 右上角 right-top
      const rmargin = 5;
      y = 5;
      const range = this.state.viewport.getProperties().voiRange || {
        lower: -1024,
        upper: 1024,
      };
      const wwwl = csUtils.windowLevel.toWindowLevel(range.lower, range.upper);
      val = "WL:" + wwwl.windowCenter.toFixed(0);
      val += " WW:" + wwwl.windowWidth.toFixed(0);
      x = cvs_w - rmargin - context.measureText(val).width;
      context.fillText(val, x, y);
      y += h;
      // Image No-Count
      val = "Im:" + (idx + 1) + "/" + this.state.series.GetCount();
      x = cvs_w - rmargin - context.measureText(val).width;
      context.fillText(val, x, y);
      y += h;
      // Series No
      val = image.SeriesNo;
      if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y += h;
      }
      // modality
      val = image.DeviceName;
      if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
      }

      // 右下角 right-bottom
      y = cvs_h - h;
      // Thickness-Location
      val = image.ThicknessLocation;
      if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y -= h;
      }

      // 曝光参数
      val = image.Exposure;
      if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y -= h;
      }
      // 拍片参数
      val = image.TrTe;
      if (val) {
        x = cvs_w - rmargin - context.measureText(val).width;
        context.fillText(val, x, y);
        y -= h;
      }
      // Zoom
      const imageData = this.state.viewport.getImageData();
      const camera = this.state.viewport.getCamera();
      let spacing = [1, 1, 1];
      if (imageData) {
        spacing = imageData.spacing;
      }
      const t = cvs_h * spacing[1] * 0.5;
      const scale = t / camera.parallelScale;
      val = "Zoom:" + scale.toFixed(2);
      x = cvs_w - rmargin - context.measureText(val).width;
      context.fillText(val, x, y);

      context.setTransform(mtx);
    },
    getOrientationMarkers({ camera, rotation }) {
      // const { rotation, previousCamera, camera } = detail;
      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;
    },
}
相关推荐
缓慢更新38 分钟前
AI 辅助生成单测:从接口定义到用例的流水线
java·服务器·前端·网络·数据库·人工智能
超级架构师1 小时前
PRAXO-CORE 2.5.0:用 conformance 和显式边界构建 Go Agent 框架
开发语言·人工智能·后端·golang·ai编程·智能体框架·praxo-core
陈随易1 小时前
AI 运维服务器,安全又可靠的方法
前端·后端·程序员
叼烟扛炮1 小时前
Linux 学习笔记(四十三):网络编程进阶——自定义协议解决 TCP 粘包与守护进程
linux·开发语言·网络·笔记·tcp/ip
风骏时光牛马2 小时前
AI稳定性治理体系构建与疑难问题深度分析
前端
LMT流氓兔2 小时前
第五单元——第十六课:给书店助手加上网页界面
java·开发语言·jvm·人工智能·oracle·langchain·1024程序员节
专注仿真2 小时前
梯度提升类(XFBoost)算法详解与代码实例
开发语言·人工智能·python·算法·大模型训练·控制算法
外收内放2 小时前
Python基础语法练习题(75)
开发语言·python·学习
IT_陈寒3 小时前
JavaScript的this坑人实录,这次我真的记下来了
前端·人工智能·后端
starzy19903 小时前
Scala循环与判断:一切皆表达式的控制流
开发语言·人工智能·scala