自学内容网 自学内容网

医学影像DICOM 处理(一)

        与医学、医院相关的项目搞起来真的是要命。。。完全生疏的方向 。。。其中合作伙伴说,让我用AI直接生成代码就可以了。。我就在想,区域链、人工智能、AI等等这些喙头啥时候是个头儿。。。资本用来圈钱的各种概念总是那么不务实!

        DICOM是医学图像和相关信息的国际标准,它定义了满足临床需要的可用于数据交换的医学图像格式,被广泛用于放射、成像的诊疗诊断设备。也就是说,在医院放射科使用的设备上读取的影像基本都是DICOM格式,包括CT、MRI、超声等的讲解及技术规范。咱就不展开讨论了,网上一堆,大家去查阅即可。

        咱的项目基本都是趋于实战,很少讲原理,因为有些原理讲起来可能我就没那么多心血来写作了,那么大篇幅的进行整理及输出。我还有我的事情要做。。。

        下来就讲讲如何在web端进行dicom图像的展示有相关操作。本次分享实现两点功能:

1、影像加载

2、影像标注

其他功能后续再一一补充实现 。

        项目安装以下依赖: 

"cornerstone-core": "^2.6.1",
"cornerstone-math": "^0.1.10",
"cornerstone-tools": "^6.0.10",
"cornerstone-wado-image-loader": "^4.13.2",
"dicom-parser": "^1.8.21",
"hammerjs": "^2.0.8",

在你项目中创建一个Vue组件页面粘贴以下代码实现一个预览组件:

<template>
    <div v-loading="loading" class="dicom" ref="dicomImage">
        <span v-if="loadFailed">加载失败</span>
    </div>
</template>
<script>
import cornerstone from 'cornerstone-core';
import dicomParser from 'dicom-parser';
import wadoImageLoader from 'cornerstone-wado-image-loader';
import cornerstoneMath from "cornerstone-math"
import cornerstoneTools from "cornerstone-tools"
import Hammer from "hammerjs"

// 配置 Web Worker
var config = {
    webWorkerPath: "cornerstone-wado-image-loader/cornerstoneWADOImageLoaderNoWebWorkers.bundle.min.js",
    taskConfiguration: {
        decodeTask: {
            codecsPath: "cornerstone-wado-image-loader/cornerstoneWADOImageLoaderCodecs.js"
        }
    }
};
wadoImageLoader.webWorkerManager.initialize(config);

cornerstoneTools.external.cornerstone = cornerstone;
cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
cornerstoneTools.external.Hammer = Hammer;

// 初始化cornerstoneTools工具
cornerstoneTools.init({
    mouseEnabled: true,// 当元素被启用时,是否监听鼠标事件
    touchEnabled: true, // 当元素被启用时,是否监听触摸事件
    globalToolSyncEnabled: true,// 全局工具同步
    showSVGCursors: true, // 显示svg光标
    autoResizeViewports: true,// 自动调整视口大小
    lineDash: [4, 4] // 虚线样式
});

wadoImageLoader.external.cornerstone = cornerstone;
wadoImageLoader.external.dicomParser = dicomParser;

export default {
    name: 'DicomPreview',
    props: {
        imageId: {
            type: String,
            required: true
        }
    },
    data() {
        return {
            loading: true,
            loadFailed: false,
        }
    },
    // watch:{
    // imageId(newValue,oldValue){
    //  var url = `wadouri:${this.imageId}`;
    //  this.loadAndViewImage(url);
    // } 
    // },
    mounted() {
        var url = `wadouri:${this.imageId}`;
        this.loadAndViewImage(url);
    },
    methods: {
        loadAndViewImage(imageId) {
            let element = this.$refs.dicomImage
            const lengthProps = {
                configuration: {
                    handleRadius: 1,
                    drawHandlesOnHover: true,
                    hideHandlesIfMoving: true,
                    digits: 2
                }
            };
            const LengthTool = cornerstoneTools.LengthTool;
            //添加获取到的窗宽,窗高工具
            cornerstoneTools.addTool(LengthTool, lengthProps);
            cornerstoneTools.addToolForElement(element, LengthTool, lengthProps);
            // 绑定工具操作功能到鼠标左键
            cornerstoneTools.setToolActive('Length', {
                mouseButtonMask: 1
            })

            //所有工具在此行前添加
            cornerstone.enable(element)
            cornerstone.loadAndCacheImage(imageId).then((image) => {
                var viewport = cornerstone.getDefaultViewportForImage(element, image);
                cornerstone.displayImage(element, image, viewport);
                this.loading = false
                this.loadFailed = false
                this.$nextTick(this.enableLengthTools())
            }, (err) => {
                console.log(err)
                this.loading = false
                this.loadFailed = true
            });
        },
        enableLengthTools() {

        },
        clearTools() {
            cornerstoneTools.clearToolState(element, 'Length');
            cornerstone.updateImage(element); // 刷新图像
        }
    }
}
</script>
<style lang="scss" scoped>
.dicom {
    height: 100%;
    width: 500px;
    height: 500px;
}
</style>

在使用的父页面中引入此子组件使用,并传参数即可:

import DicomPreview from './dicom/index.vue'

components: {
    DicomPreview
},


data() {
     return {
         lineChartData: lineChartData.newVisitis,
         imageIds: [{
                dicIds: 'http://47.107.255.46:1000/wado/SERVERAE?requestType=WADO&studyUID=1.2.392.200036.9116.2.5.1.3268.2047634718.1719992618.411948&seriesUid=840.113747.1719992443.59096.130764.1965210712314854.1337&objectUid=4.59096.130764.1965210712314854.1341&contentType=application%2Fdicom'
          }, {
                dicIds: "https://tools.cornerstonejs.org/examples/assets/dicom/bellona/chest_lung/1.dcm"
          }]
      }
},

<el-row :gutter="20">
     <el-col :span="12">
          <div class="w-100 flex-row">
              <dicom-preview :imageId="imageIds[1].dicIds" style="width: 500px;height:500px;"></dicom-preview>
          </div>
     </el-col>
      <el-col :span="12">
           <dicom-preview :imageId="imageIds[0].dicIds" style="width: 500px;height:500px;"></dicom-preview>
       </el-col>
</el-row>

如你所见,为啥两张影像显示的单位不同呢?来我们分析一下源码显示单位的逻辑:

第一个影像数据为:

第二个影像数据为:

可以看到,虽然都为影像图片,但是有些输出设备输出dicom时未携带横纵像素间距导致无法将pixel转为mm单位所致!

再贴两个页面,你自己创建两个html文件,将代码分别粘贴进去,使用浏览器打开查看体验即可:

 web.html页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://unpkg.com/hammerjs@2.0.8/hammer.js"></script>
    <script src="https://unpkg.com/cornerstone-core@2.6.1/dist/cornerstone.js"></script>
    <script src="https://unpkg.com/cornerstone-math@0.1.10/dist/cornerstoneMath.min.js"></script>
    <script src="https://unpkg.com/cornerstone-wado-image-loader@4.1.3/dist/cornerstoneWADOImageLoader.bundle.min.js"></script>
    <script src="https://unpkg.com/cornerstone-web-image-loader@2.1.1/dist/cornerstoneWebImageLoader.min.js"></script>
    <script src="https://unpkg.com/cornerstone-tools@6.0.7/dist/cornerstoneTools.js"></script>
    <script src="https://unpkg.com/dicom-parser@1.8.13/dist/dicomParser.min.js"></script>
</head>
<body>
    <!-- 用于加载图片的div区域 -->
    <div id="dicomImage" style="width: 512px;height: 512px;"></div>
</body>
<script>
    // 注册并挂载cornerstone及其cornerstoneTools,固定操作
    cornerstoneTools.external.cornerstone = cornerstone;
    cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
    cornerstoneTools.external.Hammer = Hammer;
    cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
    cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
    // imageId就是cornerstone要求的.dcm图片地址,例如:var imageId = "wadouri:http://127.0.0.1:6699/ctdcm1.dcm";
    var imageId = "wadouri:https://tools.cornerstonejs.org/examples/assets/dicom/bellona/chest_lung/1.dcm";
    // 初始化cornerstoneTools工具
    cornerstoneTools.init();
    // 获取要用于加载图片的div区域
    var element = document.getElementById('dicomImage');
    //激活获取到的用于图片加载的区域
    cornerstone.enable(element);
    // 从cornerstoneTools库中获取窗宽,窗高工具
    const WwwcTool = cornerstoneTools.WwwcTool;
    //添加获取到的窗宽,窗高工具
    cornerstoneTools.addTool(WwwcTool);
    // 绑定工具操作功能到鼠标左键
    cornerstoneTools.setToolActive('Wwwc', {
        mouseButtonMask: 1
    })
    //使用loadAndCacheImage()方法加载并缓存图片,然后使用displayImage()方法显示图片。
    cornerstone.loadAndCacheImage(imageId).then(function (image) {
        cornerstone.displayImage(element, image);
    })
</script>
</html>

web2.html页面:

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CornerstoneTools Demo</title>
    <script src="https://unpkg.com/cornerstone-core@2.3.0/dist/cornerstone.js"></script>
    <script src="https://unpkg.com/cornerstone-wado-image-loader@3.3.1/dist/cornerstoneWADOImageLoader.min.js"></script>
    <script src="https://unpkg.com/dicom-parser@1.8.7/dist/dicomParser.min.js"></script>
    <script src="https://unpkg.com/cornerstone-tools@6.0.7/dist/cornerstoneTools.js"></script>
    <script src="https://unpkg.com/cornerstone-math@0.1.10/dist/cornerstoneMath.min.js"></script>
</head>
<body>
<div id="dicomImage" style="width: 512px;height: 512px;"></div>
<button onclick="EllipticalRoiToolFun()">椭圆测量</button>
<button onclick="removeTool()">清除工具</button>
<button onclick="hideLabel()">隐藏标注</button>
<button onclick="showLabel()">显示标注</button>
<button onclick="getToolInfo()">获取指定工具的信息</button>
<button onclick="clearMarker()">清除图像上的所有标注</button>
<script>

    let imageId = "wadouri:" + "http://47.107.255.46:1000/wado/SERVERAE?requestType=WADO&studyUID=1.2.392.200036.9116.2.5.1.3268.2047634718.1719992618.411948&seriesUid=840.113747.1719992443.59096.130764.1965210712314854.1337&objectUid=4.59096.130764.1965210712314854.1341&contentType=application%2Fdicom";
    let element = document.querySelector("#dicomImage");

    /***
     * @description cornerstone初始化
     * @param imageId
     */
    function cornerstoneInit(imageId) {
        cornerstoneTools.external.cornerstone = cornerstone;
        cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
        cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
        // 初始化cornerstoneTools
        cornerstoneTools.init({
            mouseEnabled: true,// 当元素被启用时,是否监听鼠标事件
            touchEnabled: false, // 当元素被启用时,是否监听触摸事件
            globalToolSyncEnabled: true,// 全局工具同步
            showSVGCursors: true, // 显示svg光标
            autoResizeViewports: true,// 自动调整视口大小
            lineDash: [4, 4] // 虚线样式
        });

        cornerstone.enable(element);  // 初始并启用绘制的元素
        const ApiTool = cornerstoneTools[`EllipticalRoiTool`];
        cornerstoneTools.addToolForElement(element, ApiTool);  // 给指定启用元素添加指定工具
        // cornerstoneTools.addTool(ApiTool);或者,直接给全部启用元素添加指定工具
        loadImage(element, imageId); // 加载并且绘制影像到指定元素上
    }

    /***
     * @description 加载并图像
     * @param element 承载影像的容器div元素
     * @param imageId 影像Id
     */
    function loadImage(element, imageId) {
        cornerstone.loadAndCacheImage(imageId).then(image => {
            cornerstone.displayImage(element, image); // 渲染影像到指定元素
        })
    }


    /***
     * @description 椭圆测量
     * @constructor
     */
    function EllipticalRoiToolFun(){
        const options = {mouseButtonMask: 1};
        setToolActive('EllipticalRoi',options);
    }

    /***
     *@description 获取已添加的指定工具 , 可以查看工具当前的mode状态
     * mode: "disabled" , "active"
     */
    function getTool(toolName){
        const tools = cornerstoneTools.getToolForElement(element, toolName);
        console.log("已添加的工具 " + toolName +" 信息")
        return tools
    }

    /***
     * @description 给指定启用元素激活指定工具
     * @param toolName 工具名
     * @param element 影像渲染元素
     * @param options 公户配置项
     */
    function setToolActive(toolName,options){
        cornerstoneTools.setToolActiveForElement(element, toolName, options);
        // cornerstoneTools.setToolActive(toolName, options); 或者,直接激活全部启用元素的指定工具
    }

    /***
     *@description 清除工具
     */
    function removeTool() {
        cornerstoneTools.removeToolForElement(element,'EllipticalRoi'); // 给指定启用元素清除指定工具
        // cornerstoneTools.removeTool(toolName); 或者,直接清除全部启用元素的指定工具
    }

    /***
     * @description 隐藏标注
     * @desc 特此说明,当需要重新隐藏标注时,直接将工具状态禁用即可
     * @param toolName 工具名
     */
    function hideLabel(){
        cornerstoneTools.setToolDisabledForElement(element,'EllipticalRoi');
        // cornerstoneTools.setToolDisabled(toolItem.toolName); 或者,直接将全部的启用元素隐藏标注
        cornerstone.updateImage(element);   // 刷新图像,
    }

    /***
     * @description 显示标注
     * @desc 特此说明,当需要重新显示标注时,需要重新将所有工具激活即可
     * @param toolName 工具集
     */
    function showLabel(toolName){
        EllipticalRoiToolFun();
        cornerstone.updateImage(element);  // 刷新图像 , 需要重新刷新
    }

    /***
     * @description 获取指定工具的信息
     * @constructor
     */
    function getToolInfo() {
        console.log(getTool('EllipticalRoi'));
    }

    /***
     * @description 清除图像上的所有标注,永久清除
     * @desc 当需要清除图像上显示的测量标注时,需要先清空工具的 state 记录
     */
    function clearMarker(){
        cornerstoneTools.clearToolState(element, 'EllipticalRoi');
        cornerstone.updateImage(element); // 刷新图像
    }
    cornerstoneInit(imageId);
</script>
</body>
</html>

 

 右键使用浏览器打开预览即可。细节的代码注释则不进行讲解了,自己研究查看。

下面给一些官方API文档连接:打开自行研读哦。

Cornerstone Tools: Examples

Overview | Cornerstone.js


原文地址:https://blog.csdn.net/yunhuaikong/article/details/143664039

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!