dicom胶片展示,使用基石插件cornerstoneTools完成

7 篇文章 1 订阅
1 篇文章 0 订阅

我们需要把用到的文件下载到public目录,之后在vue的index.html里引用

 

我们还需要在页面里做引入


window.cornerstoneTools.external.cornerstone = window.cornerstone;
window.cornerstoneWADOImageLoader.external.cornerstone = window.cornerstone;
window.cornerstoneWADOImageLoader.external.dicomParser = window.dicomParser;
window.cornerstoneTools.external.cornerstoneMath = window.cornerstoneMath;
window.cornerstoneTools.external.Hammer = window.Hammer;

ts需要给上面的引入api定义类型,不然报错

接下来进行图片的展示并初始化功能

 const element = document.getElementById('medical-imaging');
            let imageId: string = '';
            window.cornerstone.enable(element);
            imageId = `wadouri:${data.reportUrlList[num]}`;
            window.cornerstone.loadImage(imageId).then((image: any) => {
                window.cornerstone.displayImage(element, image);
                // 激活开关
                window.cornerstoneTools.mouseInput.enable(element); // 鼠标按下事件
                window.cornerstoneTools.mouseWheelInput.enable(element); // 鼠标滚轮事件
                window.cornerstoneTools.wwwc.activate(element, 1); // 允许改变窗宽窗位
                window.cornerstoneTools.pan.activate(element, 2); // 允许平移
                window.cornerstoneTools.zoom.activate(element, 4); // 允许缩放
                window.cornerstoneTools.touchInput.enable(element); // 手势事件
                window.cornerstoneTools.zoomTouchPinch.activate(element);
                window.cornerstoneTools.length.activate(element); // 长度
                window.cornerstoneTools.probe.activate(element, 1); // 探索
                window.cornerstoneTools.ellipticalRoi.activate(element, 1); // 椭圆
                window.cornerstoneTools.rectangleRoi.activate(element, 1); // 矩形
                window.cornerstoneTools.angle.activate(element, 1); // 角度
                window.cornerstoneTools.highlight.activate(element, 1); // 高亮
                window.cornerstoneTools.freehand.activate(element, 1); // 画笔
                window.cornerstoneTools.stackScroll.activate(element); // 堆积滚动
                window.cornerstoneTools.arrowAnnotate.activate(element, 1); // 箭头注解
                window.cornerstoneTools.wwwcTouchDrag.disable(element); // 关闭灰度值
                window.cornerstoneTools.wwwc.deactivate(element, 1); // 不允许改变窗宽窗位
                // 默认开启
                window.cornerstoneTools.zoomWheel.activate(element); // 缩放
                const canvasStack = {
                    currentImageIdIndex: 0,
                    imageIds: image,
                };
                window.cornerstoneTools.addStackStateManager(element, ['stack']);
                window.cornerstoneTools.addToolState(element, 'stack', canvasStack); // 将工具状态添加到toolStateManager,这由工具以及恢复已保存状态的模块完成。addToolState(element, toolType, measurementData)
                window.cornerstoneTools.stackScrollWheel.activate(element); // Mouse wheel
                //    cornerstoneTools.scrollIndicator.enable(element); // Position indicator
            });

之后可以封装一个功能调用的方法

 const cornerstoneSwitch = (name?: string) => {
            const element = document.getElementById('medical-imaging');
            if (name && ['probe', 'rectangleRoi', 'angle', 'arrowAnnotate', 'length', 'ellipticalRoi'].includes(name)) {
                data.nameList.push(name);
            }
            if (name === 'newLoad') {
                window.cornerstone.reset(element);
            }
            if (name === 'clear') {
                if (data.nameList.length > 0) {
                    data.nameList.forEach((i) => {
                        window.cornerstoneTools.clearToolState(element, i);
                    });
                    data.nameList.length = 0;
                }
            }
            if (name === 'revocation') {
                if (data.nameList.length > 0) {
                    window.cornerstoneTools.clearToolState(element, data.nameList[data.nameList.length - 1]);
                    data.nameList.length -= 1;
                }
            }
            // 默认关闭
            window.cornerstoneTools.panTouchDrag.deactivate(element); // 拖拽-移动
            window.cornerstoneTools.probeTouch.deactivate(element); // 探索并标注所处坐标数据
            window.cornerstoneTools.zoomTouchDrag.deactivate(element); // 拖拽并放大
            window.cornerstoneTools.lengthTouch.deactivate(element); // 长度记录
            window.cornerstoneTools.ellipticalRoiTouch.deactivate(element); // 画圆/椭圆
            window.cornerstoneTools.rectangleRoiTouch.deactivate(element); // 画矩形
            window.cornerstoneTools.angleTouch.deactivate(element); // 画角
            window.cornerstoneTools.arrowAnnotateTouch.deactivate(element); // 箭头
            window.cornerstoneTools.rotateTouchDrag.deactivate(element); // 自由旋转
            window.cornerstoneTools.wwwcTouchDrag.deactivate(element); // Drag灰度值与数据值调整
            window.cornerstone.setViewport(element, {
                invert: false, // 正负片-负像
                vflip: false, // 垂直翻转
                hflip: false, // 水平翻转
            });
            // 是否开启
            window.cornerstoneTools.zoomWheel.activate(element); // 缩放
            if (name === 'panTouchDrag') {
                window.cornerstoneTools.panTouchDrag.activate(element); // 拖拽-移动
            }
            if (name === 'probe') {
                window.cornerstoneTools.probeTouch.activate(element); // 探索并标注所处坐标数据
            }
            if (name === 'zoomTouchDrag') {
                window.cornerstoneTools.zoomWheel.deactivate(element); // 关闭缩放
                window.cornerstoneTools.zoomTouchDrag.activate(element); // 拖拽并放大
            }
            if (name === 'length') {
                window.cornerstoneTools.lengthTouch.activate(element); // 长度记录
            }
            if (name === 'ellipticalRoi') {
                window.cornerstoneTools.ellipticalRoiTouch.activate(element); // 画圆/椭圆
            }
            if (name === 'rectangleRoi') {
                window.cornerstoneTools.rectangleRoiTouch.activate(element); // 画矩形
            }
            if (name === 'angle') {
                window.cornerstoneTools.angleTouch.activate(element); // 画角
            }
            if (name === 'arrowAnnotate') {
                window.cornerstoneTools.arrowAnnotateTouch.activate(element); // 箭头
            }
            if (name === 'rotateTouchDrag') {
                window.cornerstoneTools.rotateTouchDrag.activate(element); // 自由旋转
            }
            if (name === 'wwwcTouchDrag') {
                window.cornerstoneTools.wwwcTouchDrag.activate(element); // Drag灰度值与数据值调整
            }
            window.cornerstone.setViewport(element, {
                invert: name === 'invert', // 正负片-负像
                vflip: name === 'vflip', // 垂直翻转
                hflip: name === 'hflip', // 水平翻转
            });
        };

 下面是我页面的完整代码

<!-- 支持app 查看dicom医学影像 -->
<template>
    <div class="flex-page">
        <template v-if="dataLoadingOver">
            <template v-if="reportUrlList.length > 0">
                <div class="meun-list">
                    <div
                        v-for="(item, index) of items"
                        :key="item.id"
                        :class="['meun-title', { 'active-menu-title': index === checkedIndex }]"
                        @click.stop="checkedMenu(index)"
                    >
                        {{ item.name }}
                    </div>
                    <div class="shrink-btn" @click="isShrink = !isShrink"><van-icon :name="isShrink ? 'arrow-down' : 'arrow-up'" /></div>
                    <div v-show="!isShrink" class="meun-content">
                        <div
                            v-for="(item, index) of items[checkedIndex].content"
                            :key="index"
                            class="button-part"
                            :class="{ checked: index === checkedChildIndex }"
                            @click.stop="checkFunction(index, item.nameEN)"
                        >
                            <div><img :src="getImageSrc(`cloud-imagine-film/icon_${item.img}.png`)" alt="" /></div>
                            <div>{{ item.nameCN }}</div>
                        </div>
                    </div>
                </div>
                <div id="medical-imaging"></div>
                <div class="foot-part">
                    <button @click="previousPage()">上一张</button>
                    <button style="color: #fff; background: linear-gradient(332deg, #8796ff 0%, #93b1ff 100%); border: none" @click="nextPage()">下一张</button>
                </div>
            </template>
            <empty-page v-else style="height: 40rem" text="暂无数据" />
        </template>
    </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, reactive, toRefs } from 'vue';
import { commonUtils } from '@utils';
import { Icon } from 'vant';
import EmptyPage from '@components/empty-page.vue';
import procedureService from '@api/procedure.service';

window.cornerstoneTools.external.cornerstone = window.cornerstone;
window.cornerstoneWADOImageLoader.external.cornerstone = window.cornerstone;
window.cornerstoneWADOImageLoader.external.dicomParser = window.dicomParser;
window.cornerstoneTools.external.cornerstoneMath = window.cornerstoneMath;
window.cornerstoneTools.external.Hammer = window.Hammer;

export default defineComponent({
    components: {
        'empty-page': EmptyPage,
        'van-icon': Icon,
    },
    props: {
        procedureId: {
            type: String,
            required: true,
            default: '',
        },
    },
    setup: (props) => {
        let num: number = 0;
        const data = reactive({
            dataLoadingOver: false,
            checkedIndex: 0,
            checkedChildIndex: -1,
            isShrink: true,
            pageNo: 1,
            pageSize: 5,
            lastPage: false,
            items: [
                {
                    id: 0,
                    name: '图像',
                    content: [
                        { nameCN: '移动', img: 'pan', nameEN: 'panTouchDrag' },
                        { nameCN: '定点缩放', img: 'zoom', nameEN: 'zoomTouchDrag' },
                        { nameCN: '灰度值', img: 'wwwc', nameEN: 'wwwcTouchDrag' },
                        { nameCN: '自由旋转', img: 'rotate', nameEN: 'rotateTouchDrag' },
                        { nameCN: '负像', img: 'invert', nameEN: 'invert' },
                        { nameCN: '垂直翻转', img: 'vflip', nameEN: 'vflip' },
                        { nameCN: '水平翻转', img: 'hflip', nameEN: 'hflip' },
                        { nameCN: '重置', img: 'load', nameEN: 'newLoad' },
                    ],
                },
                {
                    id: 1,
                    name: '标注',
                    content: [
                        { nameCN: '标记', img: 'probe', nameEN: 'probe' },
                        { nameCN: '矩形', img: 'rectangle', nameEN: 'rectangleRoi' },
                        { nameCN: '角度', img: 'angle', nameEN: 'angle' },
                        { nameCN: '箭头', img: 'arrow', nameEN: 'arrowAnnotate' },
                        { nameCN: '长度', img: 'length', nameEN: 'length' },
                        { nameCN: '圆/椭圆', img: 'elliptical', nameEN: 'ellipticalRoi' },
                        { nameCN: '撤销', img: 'revocation', nameEN: 'revocation' },
                        { nameCN: '清空元素', img: 'clear', nameEN: 'clear' },
                    ],
                },
            ],
            nameList: [] as string[],
            reportUrlList: [] as string[],
        });
        const getDicomInfo = async () => {
            commonUtils.showLoading();
            await procedureService
                .getCloudImagingMediaUrlList(props.procedureId, data.pageNo, data.pageSize)
                .then((res) => {
                    if (!res.entityList || res.entityList.length === 0) {
                        data.lastPage = true;
                        return;
                    }
                    data.reportUrlList.push(...res.entityList);
                    data.pageNo++;
                })
                .catch((err) => {
                    commonUtils.alert(err?.responseText || '获取页面信息失败');
                })
                .finally(() => {
                    commonUtils.hideLoading();
                    data.dataLoadingOver = true;
                });
        };
        const getDetailInfo = async () => {
            const cloudImagingInfo = await procedureService.getCloudImagingInfoByProcedureId(props.procedureId, '', commonUtils.getOrgGroupId());
            document.title = cloudImagingInfo?.procedureName || '影像展示';
        };
        const dicomParser = async () => {
            commonUtils.showLoading();
            const element = document.getElementById('medical-imaging');
            let imageId: string = '';
            window.cornerstone.enable(element);
            imageId = `wadouri:${data.reportUrlList[num]}`;
            window.cornerstone.loadImage(imageId).then((image: any) => {
                window.cornerstone.displayImage(element, image);
                // 激活开关
                window.cornerstoneTools.mouseInput.enable(element); // 鼠标按下事件
                window.cornerstoneTools.mouseWheelInput.enable(element); // 鼠标滚轮事件
                window.cornerstoneTools.wwwc.activate(element, 1); // 允许改变窗宽窗位
                window.cornerstoneTools.pan.activate(element, 2); // 允许平移
                window.cornerstoneTools.zoom.activate(element, 4); // 允许缩放
                window.cornerstoneTools.touchInput.enable(element); // 手势事件
                window.cornerstoneTools.zoomTouchPinch.activate(element);
                window.cornerstoneTools.length.activate(element); // 长度
                window.cornerstoneTools.probe.activate(element, 1); // 探索
                window.cornerstoneTools.ellipticalRoi.activate(element, 1); // 椭圆
                window.cornerstoneTools.rectangleRoi.activate(element, 1); // 矩形
                window.cornerstoneTools.angle.activate(element, 1); // 角度
                window.cornerstoneTools.highlight.activate(element, 1); // 高亮
                window.cornerstoneTools.freehand.activate(element, 1); // 画笔
                window.cornerstoneTools.stackScroll.activate(element); // 堆积滚动
                window.cornerstoneTools.arrowAnnotate.activate(element, 1); // 箭头注解
                window.cornerstoneTools.wwwcTouchDrag.disable(element); // 关闭灰度值
                window.cornerstoneTools.wwwc.deactivate(element, 1); // 不允许改变窗宽窗位
                // 默认开启
                window.cornerstoneTools.zoomWheel.activate(element); // 缩放
                const canvasStack = {
                    currentImageIdIndex: 0,
                    imageIds: image,
                };
                window.cornerstoneTools.addStackStateManager(element, ['stack']);
                window.cornerstoneTools.addToolState(element, 'stack', canvasStack); // 将工具状态添加到toolStateManager,这由工具以及恢复已保存状态的模块完成。addToolState(element, toolType, measurementData)
                window.cornerstoneTools.stackScrollWheel.activate(element); // Mouse wheel
                //    cornerstoneTools.scrollIndicator.enable(element); // Position indicator
            });
            commonUtils.hideLoading();
        };
        const cornerstoneSwitch = (name?: string) => {
            const element = document.getElementById('medical-imaging');
            if (name && ['probe', 'rectangleRoi', 'angle', 'arrowAnnotate', 'length', 'ellipticalRoi'].includes(name)) {
                data.nameList.push(name);
            }
            if (name === 'newLoad') {
                window.cornerstone.reset(element);
            }
            if (name === 'clear') {
                if (data.nameList.length > 0) {
                    data.nameList.forEach((i) => {
                        window.cornerstoneTools.clearToolState(element, i);
                    });
                    data.nameList.length = 0;
                }
            }
            if (name === 'revocation') {
                if (data.nameList.length > 0) {
                    window.cornerstoneTools.clearToolState(element, data.nameList[data.nameList.length - 1]);
                    data.nameList.length -= 1;
                }
            }
            // 默认关闭
            window.cornerstoneTools.panTouchDrag.deactivate(element); // 拖拽-移动
            window.cornerstoneTools.probeTouch.deactivate(element); // 探索并标注所处坐标数据
            window.cornerstoneTools.zoomTouchDrag.deactivate(element); // 拖拽并放大
            window.cornerstoneTools.lengthTouch.deactivate(element); // 长度记录
            window.cornerstoneTools.ellipticalRoiTouch.deactivate(element); // 画圆/椭圆
            window.cornerstoneTools.rectangleRoiTouch.deactivate(element); // 画矩形
            window.cornerstoneTools.angleTouch.deactivate(element); // 画角
            window.cornerstoneTools.arrowAnnotateTouch.deactivate(element); // 箭头
            window.cornerstoneTools.rotateTouchDrag.deactivate(element); // 自由旋转
            window.cornerstoneTools.wwwcTouchDrag.deactivate(element); // Drag灰度值与数据值调整
            window.cornerstone.setViewport(element, {
                invert: false, // 正负片-负像
                vflip: false, // 垂直翻转
                hflip: false, // 水平翻转
            });
            // 是否开启
            window.cornerstoneTools.zoomWheel.activate(element); // 缩放
            if (name === 'panTouchDrag') {
                window.cornerstoneTools.panTouchDrag.activate(element); // 拖拽-移动
            }
            if (name === 'probe') {
                window.cornerstoneTools.probeTouch.activate(element); // 探索并标注所处坐标数据
            }
            if (name === 'zoomTouchDrag') {
                window.cornerstoneTools.zoomWheel.deactivate(element); // 关闭缩放
                window.cornerstoneTools.zoomTouchDrag.activate(element); // 拖拽并放大
            }
            if (name === 'length') {
                window.cornerstoneTools.lengthTouch.activate(element); // 长度记录
            }
            if (name === 'ellipticalRoi') {
                window.cornerstoneTools.ellipticalRoiTouch.activate(element); // 画圆/椭圆
            }
            if (name === 'rectangleRoi') {
                window.cornerstoneTools.rectangleRoiTouch.activate(element); // 画矩形
            }
            if (name === 'angle') {
                window.cornerstoneTools.angleTouch.activate(element); // 画角
            }
            if (name === 'arrowAnnotate') {
                window.cornerstoneTools.arrowAnnotateTouch.activate(element); // 箭头
            }
            if (name === 'rotateTouchDrag') {
                window.cornerstoneTools.rotateTouchDrag.activate(element); // 自由旋转
            }
            if (name === 'wwwcTouchDrag') {
                window.cornerstoneTools.wwwcTouchDrag.activate(element); // Drag灰度值与数据值调整
            }
            window.cornerstone.setViewport(element, {
                invert: name === 'invert', // 正负片-负像
                vflip: name === 'vflip', // 垂直翻转
                hflip: name === 'hflip', // 水平翻转
            });
        };
        const previousPage = async () => {
            if (num === 0) {
                commonUtils.showTipMessage('第一页');
            } else {
                num--;
            }
            await dicomParser();
            cornerstoneSwitch('newLoad');
            data.isShrink = true;
        };
        const nextPage = async () => {
            if (num === data.reportUrlList.length - 1) {
                if (data.lastPage) {
                    commonUtils.showTipMessage('最后一页');
                    return;
                }
                await getDicomInfo();
            } else {
                num++;
            }
            await dicomParser();
            cornerstoneSwitch('newLoad');
            data.isShrink = true;
        };
        const checkFunction = (index: number, name: string) => {
            data.checkedChildIndex = index;
            data.isShrink = true;
            cornerstoneSwitch(name);
        };
        const checkedMenu = (index: number) => {
            data.checkedIndex = index;
            data.isShrink = false;
            data.checkedChildIndex = -1;
        };
        const allData = toRefs(data);
        onMounted(async () => {
            await getDicomInfo();
            await getDetailInfo();
            if (data.reportUrlList.length > 0) {
                dicomParser();
            }
        });
        return {
            ...allData,
            previousPage,
            nextPage,
            checkFunction,
            checkedMenu,
            getImageSrc: commonUtils.getImageSrc,
        };
    },
});
</script>

<style lang="scss" scoped>
.flex-page {
    height: 100vh;
    :deep(.van-popup--center) {
        line-height: 10rem;
        text-align: center;
        font-size: 2rem;
    }
    #medical-imaging {
        margin: 2rem;
        height: 80vh;
        background-color: rgb(8, 8, 8);
    }
    .foot-part {
        padding: 1rem 2rem;
        width: 100%;
        position: fixed;
        bottom: 0;
        height: 5rem;
        display: flex;
        justify-content: space-around;
        align-items: center;
        margin-bottom: 2rem;
        button {
            background: #fff;
            font-size: 1.8rem;
            font-family: PingFang SC-Bold, PingFang SC;
            font-weight: bold;
            color: #7891ec;
            line-height: 1.8rem;
            width: 15.2rem;
            text-align: center;
            height: 4.4rem;
            line-height: 4.4rem;
            border-radius: 2.8rem;
            opacity: 1;
            border: 0.1rem solid #819cfc;
        }
    }
}
.meun-list {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    font-size: 1.4rem;
    padding: 1rem 2rem;
    color: #666666;
    position: relative;
    background: black;
    font-family: PingFang SC-Bold, PingFang SC;
    font-weight: 400;
}
.meun-title {
    margin-left: 1rem;
    line-height: 1.9rem;
    border: 1px solid transparent;
    padding: 0 0.4rem;
    &:first-child {
        margin-left: 0;
    }
}
.active-menu-title {
    border: 1px solid #819cfc;
    border-radius: 0.3rem;
    color: #7891ec;
}
.meun-content {
    width: 100%;
    height: auto;
    overflow: auto;
    display: flex;
    flex-wrap: wrap;
    background: black;
    position: absolute;
    top: 4rem;
    left: 0;
}
.button-part {
    width: 25%;
    padding: 1rem 0;
    font-size: 1.3rem;
    font-family: PingFang SC-Bold, PingFang SC;
    font-weight: 400;
    div {
        margin: 0 auto;
        text-align: center;
        img {
            width: 3rem;
            height: 3rem;
        }
    }
}
.checked {
    background: #999;
    color: black;
}
.shrink-btn {
    position: absolute;
    top: 1rem;
    right: 1rem;
}
</style>

最后是页面展示情况

今天公司又让做了一版PC端的

<template>
    <div class="container">
        <template v-if="mediaUrl || visitId">
            <div class="meun-list">
                <div
                    v-for="(item, index) of items"
                    :key="item.id"
                    :class="['meun-title', { 'active-menu-title': index === checkedIndex }]"
                    @click.stop="checkedMenu(index)"
                >
                    {{ item.name }}
                </div>
                <div class="shrink-btn" @click.stop="isShrink = !isShrink">
                    <el-icon v-if="isShrink"><icon-arrow-down /></el-icon>
                    <el-icon v-else><icon-arrow-up /></el-icon>
                </div>
                <div v-show="!isShrink" class="meun-content">
                    <div
                        v-for="(item, index) of items[checkedIndex].content"
                        :key="index"
                        class="button-part"
                        :class="{ checked: index === checkedChildIndex }"
                        @click.stop="checkFunction(index, item.nameEN)"
                    >
                        <div><img :src="getImageSrc(`consultation-management/icon_${item.img}.png`)" alt="" /></div>
                        <div>{{ item.nameCN }}</div>
                    </div>
                </div>
            </div>
            <div id="medical-imaging" @click.stop="isShrink = true"></div>
            <div class="foot">
                <button @click="previousPage">上一页</button>
                <button style="color: #fff; background: #3aa0ff; border: none" @click="nextPage">下一页</button>
            </div></template
        >
        <base-default-page v-else error-text="暂无数据" :height="'80vh'"></base-default-page>
    </div>
</template>

<script lang="ts">
import { defineComponent, reactive, toRefs, onMounted } from 'vue';
import { ArrowDown as IconArrowDown, ArrowUp as IconArrowUp } from '@element-plus/icons-vue';
import { commonUtils } from '@utils';
import { BaseDefaultPage } from '@components';
import { visitMedia } from '../api';

window.cornerstoneTools.external.cornerstone = window.cornerstone;
window.cornerstoneWADOImageLoader.external.cornerstone = window.cornerstone;
window.cornerstoneWADOImageLoader.external.dicomParser = window.dicomParser;
window.cornerstoneTools.external.cornerstoneMath = window.cornerstoneMath;
window.cornerstoneTools.external.Hammer = window.Hammer;
export default defineComponent({
    name: 'VisitDicomPreview',
    components: {
        BaseDefaultPage,
        IconArrowDown,
        IconArrowUp,
    },
    props: {
        visitId: {
            type: String,
            required: false,
            default: '',
        },
        mediaUrl: {
            type: String,
            required: true,
            default: '',
        },
    },
    setup: (props) => {
        const visitService = visitMedia.useVisitMediaService();
        let imgUrl: any[] = [];
        let num: number = 0;
        const data = reactive({
            checkedIndex: 0,
            checkedChildIndex: -1,
            isShrink: true,
            items: [
                {
                    id: 0,
                    name: '图像',
                    content: [
                        { nameCN: '移动', img: 'pan', nameEN: 'panTouchDrag' },
                        { nameCN: '定点缩放', img: 'zoom', nameEN: 'zoomTouchDrag' },
                        { nameCN: '灰度值', img: 'wwwc', nameEN: 'wwwcTouchDrag' },
                        { nameCN: '自由旋转', img: 'rotate', nameEN: 'rotateTouchDrag' },
                        { nameCN: '负像', img: 'invert', nameEN: 'invert' },
                        { nameCN: '垂直翻转', img: 'vflip', nameEN: 'vflip' },
                        { nameCN: '水平翻转', img: 'hflip', nameEN: 'hflip' },
                        { nameCN: '重置', img: 'load', nameEN: 'newLoad' },
                    ],
                },
                {
                    id: 1,
                    name: '标注',
                    content: [
                        { nameCN: '标记', img: 'probe', nameEN: 'probe' },
                        { nameCN: '矩形', img: 'rectangle', nameEN: 'rectangleRoi' },
                        { nameCN: '角度', img: 'angle', nameEN: 'angle' },
                        { nameCN: '箭头', img: 'arrow', nameEN: 'arrowAnnotate' },
                        { nameCN: '长度', img: 'length', nameEN: 'length' },
                        { nameCN: '圆/椭圆', img: 'elliptical', nameEN: 'ellipticalRoi' },
                        { nameCN: '撤销', img: 'revocation', nameEN: 'revocation' },
                        { nameCN: '清空元素', img: 'clear', nameEN: 'clear' },
                    ],
                },
            ],
            nameList: [] as string[],
        });
        const dicomParser = async (name?: string) => {
            commonUtils.showLoading();
            console.log('x');
            if (name && ['probe', 'rectangleRoi', 'angle', 'arrowAnnotate', 'length', 'ellipticalRoi'].includes(name)) {
                data.nameList.push(name);
            }
            const element = document.getElementById('medical-imaging');
            if (name === 'newLoad') {
                window.cornerstone.reset(element);
            }
            if (name === 'clear') {
                if (data.nameList.length > 0) {
                    data.nameList.forEach((i) => {
                        window.cornerstoneTools.clearToolState(element, i);
                    });
                    data.nameList.length = 0;
                }
            }
            if (name === 'revocation') {
                if (data.nameList.length > 0) {
                    window.cornerstoneTools.clearToolState(element, data.nameList[data.nameList.length - 1]);
                    data.nameList.length -= 1;
                }
            }
            let imageId: string = '';
            window.cornerstone.enable(element);
            if (props.visitId) {
                imgUrl = await visitService.getDicomUrlList(props.visitId);
                imageId = `wadouri:${imgUrl[num]}`;
            } else {
                console.log(props.mediaUrl);
                const dicomUrl = props.mediaUrl;
                console.log('dicomUrl :>> ', dicomUrl);
                imageId = `wadouri:${dicomUrl}`;
            }
            window.cornerstone.loadImage(imageId).then((image: any) => {
                window.cornerstone.displayImage(element, image);
                // 激活开关
                window.cornerstoneTools.mouseInput.enable(element); // 鼠标按下事件
                window.cornerstoneTools.mouseWheelInput.enable(element); // 鼠标滚轮事件
                window.cornerstoneTools.touchInput.enable(element); // 手势事件
                window.cornerstoneTools.zoomTouchPinch.activate(element, 1);
                // window.cornerstoneTools.highlight.activate(element, 1); // 高亮
                // window.cornerstoneTools.stackScroll.activate(element); // 堆积滚动
                // 默认开启
                window.cornerstoneTools.zoomWheel.activate(element); // 缩放
            });
            commonUtils.hideLoading();
        };
        const cornerstoneSwitch = (name?: string) => {
            const element = document.getElementById('medical-imaging');
            if (name && ['probe', 'rectangleRoi', 'angle', 'arrowAnnotate', 'length', 'ellipticalRoi'].includes(name)) {
                data.nameList.push(name);
            }
            if (name === 'newLoad') {
                window.cornerstone.reset(element);
            }
            if (name === 'clear') {
                if (data.nameList.length > 0) {
                    data.nameList.forEach((i) => {
                        window.cornerstoneTools.clearToolState(element, i);
                    });
                    data.nameList.length = 0;
                }
            }
            if (name === 'revocation') {
                if (data.nameList.length > 0) {
                    window.cornerstoneTools.clearToolState(element, data.nameList[data.nameList.length - 1]);
                    data.nameList.length -= 1;
                }
            }
            // 默认关闭
            window.cornerstoneTools.wwwc.deactivate(element, 1); // 不允许开启灰度值
            window.cornerstoneTools.zoom.deactivate(element, 1); // 不不允许定点缩放
            window.cornerstoneTools.freehand.deactivate(element, 1); // 画笔
            window.cornerstoneTools.pan.deactivate(element, 1); // 允许平移
            window.cornerstoneTools.panTouchDrag.deactivate(element); // 拖拽-移动
            window.cornerstoneTools.probe.deactivate(element, 1); // 探索
            window.cornerstoneTools.probeTouch.deactivate(element); // 探索并标注所处坐标数据
            window.cornerstoneTools.zoomTouchDrag.deactivate(element); // 拖拽并放大
            window.cornerstoneTools.length.deactivate(element); // 长度
            window.cornerstoneTools.lengthTouch.deactivate(element); // 长度记录
            window.cornerstoneTools.ellipticalRoi.deactivate(element, 1); // 椭圆
            window.cornerstoneTools.ellipticalRoiTouch.deactivate(element); // 画圆/椭圆
            window.cornerstoneTools.rectangleRoi.deactivate(element, 1); // 矩形
            window.cornerstoneTools.rectangleRoiTouch.deactivate(element); // 画矩形
            window.cornerstoneTools.angleTouch.deactivate(element); // 画角
            window.cornerstoneTools.angle.deactivate(element, 1); // 角度
            window.cornerstoneTools.arrowAnnotate.deactivate(element, 1); // 箭头注解
            window.cornerstoneTools.arrowAnnotateTouch.deactivate(element); // 箭头
            window.cornerstoneTools.rotateTouchDrag.deactivate(element); // 自由旋转
            window.cornerstoneTools.wwwcTouchDrag.deactivate(element); // Drag灰度值与数据值调整
            window.cornerstoneTools.wwwcTouchDrag.disable(element); // 关闭灰度值
            window.cornerstone.setViewport(element, {
                invert: false, // 正负片-负像
                vflip: false, // 垂直翻转
                hflip: false, // 水平翻转
            });
            // 是否开启
            window.cornerstoneTools.zoomWheel.activate(element); // 缩放
            if (name === 'panTouchDrag') {
                window.cornerstoneTools.pan.activate(element, 1); // 允许平移

                window.cornerstoneTools.panTouchDrag.activate(element); // 拖拽-移动
            }
            if (name === 'probe') {
                window.cornerstoneTools.probe.activate(element, 1); // 探索
                window.cornerstoneTools.probeTouch.activate(element); // 探索并标注所处坐标数据
            }
            if (name === 'zoomTouchDrag') {
                window.cornerstoneTools.zoomWheel.deactivate(element); // 关闭缩放
                window.cornerstoneTools.zoom.activate(element, 1); // 允许定点缩放
                window.cornerstoneTools.zoomTouchDrag.activate(element); // 拖拽并放大
            }
            if (name === 'length') {
                window.cornerstoneTools.freehand.activate(element, 1); // 画笔

                window.cornerstoneTools.length.activate(element); // 长度
                window.cornerstoneTools.lengthTouch.activate(element); // 长度记录
            }
            if (name === 'ellipticalRoi') {
                window.cornerstoneTools.ellipticalRoi.activate(element, 1); // 椭圆
                window.cornerstoneTools.ellipticalRoiTouch.activate(element); // 画圆/椭圆
            }
            if (name === 'rectangleRoi') {
                window.cornerstoneTools.rectangleRoi.activate(element, 1); // 矩形
                window.cornerstoneTools.rectangleRoiTouch.activate(element); // 画矩形
            }
            if (name === 'angle') {
                window.cornerstoneTools.angleTouch.activate(element); // 画角
                window.cornerstoneTools.angle.activate(element, 1); // 角度
            }
            if (name === 'arrowAnnotate') {
                window.cornerstoneTools.arrowAnnotate.activate(element, 1); // 箭头注解
                window.cornerstoneTools.arrowAnnotateTouch.activate(element); // 箭头
            }
            if (name === 'rotateTouchDrag') {
                window.cornerstoneTools.rotateTouchDrag.activate(element); // 自由旋转
            }
            if (name === 'wwwcTouchDrag') {
                window.cornerstoneTools.wwwc.activate(element, 1); // 允许开启灰度值

                window.cornerstoneTools.wwwcTouchDrag.enable(element); // 开启灰度值
                window.cornerstoneTools.wwwcTouchDrag.activate(element); // Drag灰度值与数据值调整
            }
            window.cornerstone.setViewport(element, {
                invert: name === 'invert', // 正负片-负像
                vflip: name === 'vflip', // 垂直翻转
                hflip: name === 'hflip', // 水平翻转
            });
        };
        const previousPage = async () => {
            if (num === 0) {
                commonUtils.alert('第一页');
            } else {
                num--;
            }
            await dicomParser();
            cornerstoneSwitch('newLoad');
            data.isShrink = true;
        };
        const nextPage = async () => {
            if (props.visitId) {
                if (num === imgUrl.length - 1) {
                    commonUtils.alert('最后一页');
                } else {
                    num++;
                }
                await dicomParser();
                cornerstoneSwitch('newLoad');
            } else {
                commonUtils.alert('最后一页');
            }
            data.isShrink = true;
        };
        const checkFunction = (index: number, name: string) => {
            data.checkedChildIndex = index;
            data.isShrink = true;
            cornerstoneSwitch(name);
        };
        const checkedMenu = (index: number) => {
            data.checkedIndex = index;
            data.isShrink = false;
            data.checkedChildIndex = -1;
        };
        const allData = toRefs(data);
        onMounted(() => {
            if (props.mediaUrl || props.visitId) {
                dicomParser();
            }
        });
        return {
            imgUrl,
            previousPage,
            nextPage,
            ...allData,
            checkFunction,
            checkedMenu,
            getImageSrc: commonUtils.getImageSrc,
        };
    },
});
</script>

<style lang="scss" scoped>
.container {
    width: 100%;
    height: 80vh;
    background-color: white;
}
#medical-imaging {
    height: 65vh;
    margin: 2rem;
    background-color: rgb(8, 8, 8);
}
.foot {
    padding: 1rem 2rem;
    width: 100%;
    height: 5rem;
    display: flex;
    justify-content: space-around;
    align-items: center;
    margin-bottom: 2rem;
    button {
        background: #fff;
        font-size: 1.8rem;
        font-family: PingFang SC-Bold, PingFang SC;
        font-weight: bold;
        color: #3aa0ff;
        line-height: 1.8rem;
        width: 15.2rem;
        text-align: center;
        height: 4.4rem;
        line-height: 4.4rem;
        border-radius: 2.8rem;
        opacity: 1;
        border: 0.1rem solid #3aa0ff;
    }
}
.meun-list {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    font-size: 1.4rem;
    padding: 1rem 2rem;
    color: #666666;
    position: relative;
    background: black;
    font-family: PingFang SC-Bold, PingFang SC;
    font-weight: 400;
}
.meun-title {
    margin-left: 1rem;
    line-height: 1.9rem;
    border: 1px solid transparent;
    padding: 0 0.4rem;
    &:first-child {
        margin-left: 0;
    }
}
.active-menu-title {
    border: 1px solid #3aa0ff;
    border-radius: 0.3rem;
    color: #3aa0ff;
}
.meun-content {
    width: 100%;
    height: auto;
    overflow: auto;
    display: flex;
    flex-wrap: wrap;
    background: black;
    position: absolute;
    top: 4rem;
    left: 0;
}
.button-part {
    width: 25%;
    padding: 1rem 0;
    font-size: 1.3rem;
    font-family: PingFang SC-Bold, PingFang SC;
    font-weight: 400;
    div {
        margin: 0 auto;
        text-align: center;
        img {
            width: 3rem;
            height: 3rem;
        }
    }
}
.checked {
    background: #999;
    color: black;
}
.shrink-btn {
    position: absolute;
    top: 1rem;
    right: 1rem;
}
</style>

  • 9
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 23
    评论
### 回答1: 要读取DICOM图像并显示图像,您可以使用PyDICOM库和Matplotlib库。以下是一个简单的示例代码,可以读取DICOM文件并将其显示为图像: ```python import pydicom import matplotlib.pyplot as plt # 读取DICOM文件 ds = pydicom.dcmread("path/to/dicom/file.dcm") # 获取像素数据并转换为numpy数组 arr = ds.pixel_array # 显示图像 plt.imshow(arr, cmap='gray') plt.show() ``` 在这里,我们使用`pydicom.dcmread()`函数来读取DICOM文件并将其存储在`ds`对象中。然后,我们使用`ds.pixel_array`来获取图像的像素数据,并将其转换为NumPy数组。最后,我们使用Matplotlib的`imshow()`函数来显示图像,并使用`plt.show()`来显示它。 请注意,上述代码只显示了一幅图像,如果您想显示多幅图像,则需要使用循环遍历DICOM文件夹并显示每幅图像。 ### 回答2: Python可以使用pydicom库来读取和展示dicom文件中的图像。 首先,需要安装pydicom库。可以使用以下命令在终端或命令提示符中进行安装: ``` pip install pydicom ``` 然后,可以使用以下代码读取dicom文件和展示其中的图像: ```python import pydicom import matplotlib.pyplot as plt # 读取dicom文件 ds = pydicom.dcmread('path_to_dicom_file.dcm') # 检查是否包含图像 if 'PixelData' in ds: # 获取像素数据 pixel_data = ds.pixel_array # 展示图像 plt.imshow(pixel_data, cmap=plt.cm.gray) plt.axis('off') plt.show() else: print('该dicom文件不包含图像。') ``` 在上面的代码中,我们首先使用`pydicom.dcmread()`函数读取dicom文件。然后,我们检查是否包含图像数据,可以通过查看是否存在`'PixelData'`属性来进行判断。如果存在图像数据,我们可以使用`ds.pixel_array`来获取像素数据,并使用`plt.imshow()`函数将图像展示出来。 最后,使用`plt.axis('off')`可以隐藏图像的坐标轴,使其更加美观。使用`plt.show()`函数将图像显示出来。 如果dicom文件中包含多张图像,可以使用循环来展示每张图像,或者使用索引来选择展示特定的图像。 ### 回答3: 在Python中,可以使用pydicom库来读取和展示DICOM图像。 首先,需要安装pydicom库。可以使用以下命令来安装: ``` pip install pydicom ``` 然后,可以使用以下代码来读取DICOM图像并展示: ```python import pydicom import matplotlib.pyplot as plt # 读取DICOM文件 ds = pydicom.dcmread('path_to_dicom_file.dcm') # 将像素数据转换为二维数组 image = ds.pixel_array # 展示图像 plt.imshow(image, cmap=plt.cm.gray) plt.axis('off') plt.show() ``` 在代码中,首先使用pydicom.dcmread()函数读取DICOM文件。然后,通过访问ds.pixel_array属性将像素数据转换为二维数组。最后,使用plt.imshow()函数将图像展示出来。 需要注意的是,matplotlib库被用来展示图像,因此需要安装此库: ``` pip install matplotlib ``` 如果你使用的是Jupyter Notebook或类似的环境,可以使用%matplotlib inline命令来确保图像在输出中正确地显示。 以上就是使用Python读取DICOM图像并展示的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JianZhen✓

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值