Cornerstone.js之Cornerstone在Vue中的应用

5,098 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

介绍

Cornerstone是一套JavaScript底层组件,用于支持医学影像的显示与交互;OHIF Viewer是一套基于Cornerstone开发的纯网页版医学影像浏览前端。如同它的名字一样,Cornerstone为医学影像Web前端开发提供基石;OHIF Viewer则是基于这套基石开发的Web前端应用。

Cornerstone是底层基石,OHIF Viewer是上层应用。

在Cornerstone之上,还封装开发了一个更高层级的工具组件库Cornerstone Tools;

更多详情可以参考我的另一篇文章Cornerstone.js之Cornerstone初识

演示

图片.png

使用前提

需要新建一个vue项目和引入element

具体创建步骤参考 vue项目的创建和vue中引入element-ui或element-plus

安装 Cornerstone

npm install --save cornerstone-core cornerstone-math cornerstone-tools hammerjs cornerstone-web-image-loader

图片.png

引入和使用步骤

引入Cornerstone

// 渲染我们的图像,并提供有用的事件和方法来使响应视口变化的工具成为可能

import cornerstone from "cornerstone-core"

// 某些工具用于辅助向量数学或其他复杂运算的依赖项

import cornerstoneMath from "cornerstone-math"

import cornerstoneTools from "cornerstone-tools"

// 触摸事件和手势的跨浏览器支持

import Hammer from "hammerjs"

// web图片加载

import cornerstoneWebImageLoader from "cornerstone-web-image-loader"

cornerstoneTools.external.cornerstone = cornerstone

cornerstoneTools.external.Hammer = Hammer

cornerstoneTools.external.cornerstoneMath = cornerstoneMath

cornerstoneWebImageLoader.external.cornerstone = cornerstone

图片.png

创建一个标签

图片.png

初始化工具和初始化数据

图片.png

初始化标注工具

图片.png

加载图像

图片.png

添加工具

图片.png

激活工具

图片.png

保存工具状态

图片.png

加载工具状态

图片.png

清除工具状态

使用了哪几个工具,在销毁时,别忘记全部清除。

图片.png

完整代码

<template>

    <div class="wrapper" v-loading="loading">

        <el-row class="Container">

            <!--菜单栏--图片列表-->

            <el-col :span="4">

                <div class="menuBar">

                    <li

                        @click="choose(index, item)"

                        :class="{ clickClass: activeIndex === index }"

                        v-for="(item, index) in group"

                        :key="index"

                    >

                        <!-- 已标注 -->

                        <img

                            v-if="item.state === 'complete'"

                            :src="completeMark"

                        />

                        <!-- 未标注 -->

                        <img

                            v-else-if="item.state === 'wait'"

                            :src="waitMark"

                        />

                        <span>{{ item.dataName }}</span>

                    </li>

                </div>

            </el-col>

            <!--      标注区域-->

            <el-col :span="20">

                <div class="mainBar">

                    <div class="toolBar">

                        <div class="tool">

                            <img

                                :src="rectangleRoiImg"

                                alt="标注笔"

                                title="标注笔"

                                @click="activeTool(cornerstoneToolsType)"

                            />

                        </div>

                        <div class="tool">

                            <img

                                :src="eraserImg"

                                alt="橡皮擦"

                                title="橡皮擦"

                                @click="activeTool('Eraser')"

                            />

                        </div>

                    </div>

                    <div style="width: 100%">

                        <div id="cornerstone" class="imgContainer"></div>

                    </div>

                </div>

            </el-col>

        </el-row>

    </div>

</template>




<script>

// 渲染我们的图像,并提供有用的事件和方法来使响应视口变化的工具成为可能

import cornerstone from "cornerstone-core"

// 某些工具用于辅助向量数学或其他复杂运算的依赖项

import cornerstoneMath from "cornerstone-math"

import cornerstoneTools from "cornerstone-tools"

// 触摸事件和手势的跨浏览器支持

import Hammer from "hammerjs"

// web图片加载

import cornerstoneWebImageLoader from "cornerstone-web-image-loader"




cornerstoneTools.external.cornerstone = cornerstone

cornerstoneTools.external.Hammer = Hammer

cornerstoneTools.external.cornerstoneMath = cornerstoneMath

cornerstoneWebImageLoader.external.cornerstone = cornerstone




export default {

    name: "editAnnotation",

    data() {

        return {

            cornerstoneToolsType: "RectangleRoi",

            loading: false,

            // 已标注

            completeMark: require("../../assets/image/dataAnnotation/yiwancheng.png"),

            // 未标注

            waitMark: require("../../assets/image/dataAnnotation/daishenhe.png"),

            // 标注笔

            rectangleRoiImg: require("../../assets/image/dataAnnotation/pencil.png"),

            // 橡皮擦

            eraserImg: require("../../assets/image/dataAnnotation/eraser.png"),

            // 左侧菜单

            activeIndex: -1,

            group: [],

            // 中间图片标注

            imgSrc: "",

            ele: null,

            toolDatas: null,

            markeData: {},

            // markeData: [],

            markeImgName: "",

            markImgId: ""

        }

    },

    mounted() {

        console.log("初始化")

        this.$nextTick(() => {

            // 自定义数据

            let group = [

                {

                    id: "3587",

                    dataIo: "https://img-blog.csdnimg.cn/f05140deecf5426a8348600b04a1511b.png",

                    dataName: "wait-f15d275d82508c72b0d6eec84f11f0f.jpg",

                    state: "wait"

                },

                {

                    id: "3588",

                    dataIo: "https://img-blog.csdnimg.cn/52d607e5ca44450491eae93fdf8916ad.png",

                    dataName: "complete-dd17ee5124dcb64154f82e8d0fe4755.png",

                    state: "complete"

                }

            ]

            this.imgSrc =

                "https://img-blog.csdnimg.cn/f05140deecf5426a8348600b04a1511b.png"

            this.group = group

            this.activeIndex = 0

            // 初始化

            this.initCornerstoneTools()

            // 加载标注状态

            this.loadToolStates()

        })

    },

    methods: {

        // 切换图片

        choose(index, item) {

            if (this.activeIndex === index) return

            // 保存标注内容

            this.saveToolData()

            this.activeIndex = index

            // this.markeData = {}

            this.activeIndex = index

            this.markImgId = item.id

            this.markeImgName = item.dataName

            this.imgSrc = item.dataIo

            this.clearToolState()

            this.loadToolStates()

            this.loadWebImg(this.imgSrc)

        },

        // 保存标注信息

        save() {

            this.saveToolData()

            // 标注数据

            let labelmeData = this.markeData[[this.markeImgName]]

        },

        // 初始化标注工具

        initCornerstoneTools() {

            cornerstoneTools.init({

                showSVGCursors: true

            })

            // ////console.log(cornerstoneTools)

            // 获取元素标签

            this.ele = document.querySelector("#cornerstone")

            cornerstone.enable(this.ele)

            // this.loadWebImg("https://gimg2.baidu.com/image_search/src=http%3A%2F%2Ffile02.16sucai.com%2Fd%2Ffile%2F2014%2F0917%2F6f7a420c6fc8234bd6239f60057da72d.jpg&refer=http%3A%2F%2Ffile02.16sucai.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1628411060&t=d1f3ec89fe316967003e1f757a0fb1a6");

            // 加载图像

            this.loadWebImg(this.imgSrc)

            // 添加方形选框工具

            this.addTools()

            // this.activeTool("RectangleRoi")

            // 激活工具

            this.activeTool(this.cornerstoneToolsType)

            // 添加选框颜色

            cornerstoneTools.toolColors.setToolColor("green")

        },

        // 加载图像

        loadWebImg(url) {

            console.log("图片正在加载中")

            cornerstone.loadAndCacheImage(url).then(image => {

                cornerstone.displayImage(this.ele, image)

            })

        },

        // 添加方形选框工具

        addTools() {

            // 添加工具

            console.log("工具正在加载中")

            // 方形选框

            cornerstoneTools.addTool(

                cornerstoneTools.RectangleRoiTool,

                this.ele

            )

            // 橡皮擦

            cornerstoneTools.addTool(cornerstoneTools.EraserTool, this.ele)

        },

        // 激活工具

        activeTool(toolName) {

            // 启用工具

            // { mouseButtonMask: 1 }  //鼠标左键点击触发

            // { mouseButtonMask: 2 }  //鼠标右键点击触发

            // { mouseButtonMask: 4 }  //鼠标滚轮键点击触发

            cornerstoneTools.setToolActive(toolName, { mouseButtonMask: 1 })

        },

        // 清除工具

        clearToolState() {

            if (!this.ele) return

            // cornerstoneTools.clearToolState(this.ele, "RectangleRoi")



            cornerstoneTools.clearToolState(this.ele, this.cornerstoneToolsType)

            cornerstone.updateImage(this.ele)

        },

        // 保存工具状态

        saveToolData() {

            let data = cornerstoneTools.getToolState(

                this.ele,

                this.cornerstoneToolsType

            )

                ? JSON.parse(

                      JSON.stringify(

                          cornerstoneTools.getToolState(

                              this.ele,

                              this.cornerstoneToolsType

                          ).data

                      )

                  )

                : null

            if (!data) return

            // this.markeData[this.markeImgName] = data

            this.markeData[this.group[this.activeIndex].id] = data

        },

        // 加载工具状态

        loadToolStates() {

            const toolDatas = this.markeData[this.group[this.activeIndex].id]

            // const toolDatas = this.markeData[[this.markeImgName]]

            console.log(toolDatas)

            if (!toolDatas) return

            setTimeout(() => {

                toolDatas.forEach(data => {

                    cornerstoneTools.addToolState(

                        this.ele,

                        this.cornerstoneToolsType,

                        data

                    )

                })

                cornerstone.updateImage(this.ele)

            }, 300)

        }

    },

    beforeDestroy() {

        this.clearToolState()

    }

}

</script>



<style lang="scss" scoped>

.wrapper {

    text-align: left;




    .Container {

        border-top: 1px solid #b8cee0;

        padding-top: 15px;

    }

    .menuBar {

        height: 90vh;

        border: solid 1px grey;

        margin-left: 10px;

        overflow: auto;

        width: 100%;



        li {

            cursor: pointer;

            list-style: none;

            height: 50px;

            white-space: nowrap;

            padding-left: 10px;

            display: flex;

            justify-content: flex-start;

            align-items: center;

            min-width: max-content;

            img {

                width: 34px;

            }

            span {

                margin-left: 10px;

            }

        }

        //li选中颜色

        .clickClass {

            background: darken(#a7a7a7, 5%);

            width: 100%;

        }

        //滚动条

        &::-webkit-scrollbar {

            height: 15px;

            width: 15px;

        }


        &::-webkit-scrollbar-thumb {

            border-radius: 10px;

            box-shadow: inset 0 0 10px rgba(140, 140, 140, 0.8);

        }

    }



    .mainBar {

        margin: 0 16px;

        display: flex;

        flex-direction: row;

        .toolBar {

            display: flex;

            flex-direction: column;

            justify-content: flex-start;

            align-items: center;

            width: 40px;

            background: #e8ebee;


            .tool {

                width: 30px;

                margin: 0 5px;

                height: 36px;

                display: flex;

                justify-content: center;

                align-items: center;

                border-bottom: 1px solid #7a90ab;


                img {

                    cursor: pointer;

                    width: 22px;

                }

            }

        }

        .imgContainer {

            height: 90vh;

            border: 1px solid blue;

        }

    }

}

</style>

好了,本篇文章就到这了,下一节,我会讲一下如何在VUE中如何二次开发cornerstone。

24_Neraland1_4k.jpg