基于cornerstone3D的dicom影像瀏覽器 第三十一章 從PACS服務加載圖像

文章目錄

  • 前言
  • 一、兩個服務接口
    • 1. 查詢檢查接口
    • 2. 查詢圖像接口
  • 二、查詢界面組件
  • 三、修改歸檔
  • 總結


前言

"基于cornerstone3D的dicom影像瀏覽器"系列文章中都是加載本地文件夾的的dicom圖像。
作為一個合格的dicom影像瀏覽器需要對接PACS服務端,從PACS服務查詢檢查,下載圖像。
本章實現一個查詢界面,對接PACS服務。
效果如下 :
在這里插入圖片描述


一、兩個服務接口

PACS服務需要提供兩個接口

  1. 查詢檢查接口
  2. 查詢圖像接口

1. 查詢檢查接口

接口名稱可自定義,本文中的接口名稱:“http://localhost:9000/queryStudy”
查詢參數可自定義,本文中的接口參數有:

startDate    // 檢查開始日期
endDate      // 檢查結束日期
studyId      // 檢查號
modality     // 設備類型
name         // 姓名

示例:
http://localhost:9000/queryStudy?startDate=2000-06-09&endDate=2025-06-09&studyId=2&modality=CT

返回數據示例:

[{"No": "1","StudyId": "2","PatName": "程**","Sex": "女","Age": "43Y","ImageNum": "1","MzId": "","Modality": "CT","RadiId": "CT0000000001234567","StudyDate": "2020-08-25 10:03:33","ExamItem": "胸部X線計算機體層(CT)平掃","ExamPart": ""},{"No": "2","StudyId": "4","PatName": "贏**","Sex": "女","Age": "63Y","ImageNum": "1","MzId": "","Modality": "CT","RadiId": "CT0000000002","StudyDate": "2020-08-25 10:17:01","ExamItem": "顱腦X線計算機體層(CT)平掃","ExamPart": ""},{"No": "3","StudyId": "13","PatName": "余*","Sex": "女","Age": "37Y","ImageNum": "1","MzId": "","Modality": "CT","RadiId": "CT0000000003","StudyDate": "2022-11-14 16:41:29","ExamItem": "DR胸椎正位 *(1)","ExamPart": ""}...
]

2. 查詢圖像接口

接口名稱可自定義,本文中的接口名稱:“http://localhost:9000/queryImage”
參數:

studyId   // 檢查號

示例:http://localhost:9000/queryImage?studyId=2

返回數據示例:

["http://localhost:9000/pacs/CT/2020-08-25/2/c8353e44b039eca9b334e78b741f3b35/1.dcm","http://localhost:9000/pacs/CT/2020-08-25/2/c8353e44b039eca9b334e78b741f3b35/2.dcm","http://localhost:9000/pacs/CT/2020-08-25/2/c8353e44b039eca9b334e78b741f3b35/3.dcm","http://localhost:9000/pacs/CT/2020-08-25/2/c8353e44b039eca9b334e78b741f3b35/4.dcm",...
]

二、查詢界面組件

onSearch 查詢檢查,顯示到列表
onRowClick 查詢一次檢查所有圖像,并歸檔

<template><div class="pacs"><el-dialog:title="查詢檢查"draggablev-model="visible":modal="false":close-on-click-modal="false"width="840px"@keydown.native.stop><div class="querycond"><el-form :model="form" label-width="100px" @submit.prevent><el-row :gutter="0"><el-col :span="12"><el-form-item :label="檢查號:"><el-input v-model="form.idNumber"></el-input></el-form-item></el-col><el-col :span="7"><el-form-item :label="姓名:"><el-input v-model="form.name"></el-input></el-form-item></el-col><el-col :span="5"><el-form-item class="right-align" label-width="30px"><el-button type="primary" @click="onSearch"><el-icon><Search /></el-icon><span style="vertical-align: middle">查詢</span></el-button></el-form-item></el-col></el-row><el-row :gutter="0"><el-col :span="12"><el-form-item :label="檢查日期:"><el-date-pickerv-model="form.queryDate"type="daterange"align="right"unlink-panels:range-separator="至":shortcuts="shortcuts"></el-date-picker></el-form-item></el-col><el-col :span="7"><el-form-item :label="檢查類型:"><el-select v-model="form.modality" placeholder=""><el-optionv-for="mod in modalities":key="mod":label="mod":value="mod"></el-option></el-select></el-form-item></el-col><el-col :span="5"><el-form-item class="right-align" label-width="30px"><el-button @click="onClear"><el-icon><Delete /></el-icon><span style="vertical-align: middle">清空</span></el-button></el-form-item></el-col></el-row></el-form></div><el-table :data="studyData" border height="420px" @row-dblclick="onRowClick"><el-table-columnproperty="StudyId":label="檢查號"width="100":show-overflow-tooltip="true"></el-table-column><el-table-columnproperty="PatName":label="姓名"width="100":show-overflow-tooltip="true"></el-table-column><el-table-columnproperty="Sex":label="性別"width="80"></el-table-column><el-table-columnproperty="Age":label="年齡"width="80"></el-table-column><el-table-columnproperty="StudyDate":label="檢查日期"width="168":show-overflow-tooltip="true"></el-table-column><el-table-columnproperty="Modality":label="設備"width="90"></el-table-column><el-table-columnproperty="ExamItem":label="檢查項目"width="220":show-overflow-tooltip="true"></el-table-column></el-table></el-dialog></div>
</template><script lang="js" setup name="SearchPACS">
import { ref, reactive, onMounted } from "vue";
import { desensitizeSubstring } from "@/utils";
import { useArchiveStore } from "../stores/archive";
import { ElMessage } from "element-plus";const archiveStore = useArchiveStore();
const studyData = ref([]);
const visible = ref(false);
const modalities = ["ALL", "CR", "DX", "MG", "CT", "MR", "RF", "OT", "XA"];
const form = reactive({idNumber: "",name: "",modality: "ALL",queryDate: [new Date(), new Date()],
});const shortcuts: [{text: "今天",value: () => {const end = new Date();const start = new Date();return [start, end];},},{text: "昨天",value: () => {const end = new Date();const start = new Date();start.setTime(start.getTime() - 3600 * 1000 * 24);return [start, end];},},{text: "最近三天",value: () => {const end = new Date();const start = new Date();start.setTime(start.getTime() - 3600 * 1000 * 24 * 3);return [start, end];},},{text: "最近一周",value: () => {const end = new Date();const start = new Date();start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);return [start, end];},},{text: "最近一個月",value: () => {const end = new Date();const start = new Date();start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);return [start, end];},},{text: "最近一年",value: () => {const end = new Date();const start = new Date();start.setTime(start.getTime() - 3600 * 1000 * 24 * 365);return [start, end];},},
];const show = () => {visible.value = true;
};const onSearch = () => {// 查詢檢查服務接口,實際可存儲到配置中const studyapi = "http://localhost:9000/queryStudy";let url = studyapi;const sdate = form.queryDate[0];const edate = form.queryDate[1];url += "?startDate=" + sdate + "&endDate=" + edate;if (form.modality !== "ALL") {url += "&modality=" + form.modality;}if (form.idNumber) {url += "&id=" + form.idNumber;}if (form.name) {url += "&name=" + form.name;}//console.log(url);fetch(url).then((response) => response.json()).then((data) => {// console.log(data);studyData.value = data.map((item) => {return {...item, PatName: desensitizeSubstring(item.PatName, 1, -1) }});// console.log(studyData.value);}).catch((error) => {console.log(error);ElMessage.error("查詢失敗");});};const onClear = () => {form.idNumber = "";form.name = "";form.modality = "ALL";form.queryDate = [new Date(), new Date()];studyData.value = [];
};const onRowClick = (row) => {// 查詢圖像服務接口,實際可存儲到配置中const imageapi = "http://localhost:9000/queryImage";let url;let params = "studyId=" + row.StudyId;url = imageapi + "?" + params;// console.log(url);ElMessage.success("正在獲取圖像, 請稍候...");visible.value = false;fetch(url).then((response) => response.json()).then((data) => {// console.log(data);const imageIds = data.map((item) => "dicomweb:" + item);//console.log("imageIds: ", imageIds);imageIds.forEach((imageId) => {archiveStore.archiveFile(imageId);});}).catch((error) => {console.log(error);ElMessage.error("查詢失敗");});
};defineExpose({show,
});</script><style lang="scss" scoped>
:deep(.el-dialog) {padding: 1px;border: 1px solid gray;border-radius: 4px;
}
:deep(.el-dialog__header) {background-color: #eee;height: 40px;padding: 8px 8px;border: none;
}:deep(.el-dialog__title) {color: #444;
}:deep(.el-table__body-wrapper) {background-color: white;
}:deep(.el-table__header .is-leaf) {background-color: white;color: #444;
}:deep(.el-table__cell) {background-color: white;color: #444;padding: 4px 0px;
}:deep(.el-table--enable-row-hover .el-table__body tr:hover > td) {background-color: #d3e3fd;
}:deep(.el-table--border .el-table__cell:first-child .cell) {padding-left: 4px;
}.querycond {width: 100%;height: 100px;padding: 8px 0;background-color: white;
}:deep(.el-form-item) {margin-bottom: 4px;
}:deep(.el-form-item__label) {color: #444;
}:deep(.el-form-item__content .el-input .el-input__inner) {height: 30px;line-height: 30px;padding: 0px 8px;
}:deep(.el-button) {height: 32px;width: 100px;line-height: 32px;padding: 0;
}:deep(.el-range-editor.el-input__inner) {height: 32px;padding: 0 10px;
}
:deep(.el-date-editor--daterange) {width: 320px;
}:deep(.el-date-editor .el-range-separator) {padding: 0;width: 8%;
}
</style>

三、修改歸檔

之前只對本地文件歸檔,現增加對網絡文件歸檔的兼容
歸檔邏輯請查看第四章 加載本地文件夾中的dicom文件并歸檔

修改archiveStore.js文件中的archiveFile函數。
修改前:

async function archiveFile(file) {const imageId = cornerstoneDICOMImageLoader.wadouri.fileManager.add(file);const dcmImage = new DCMImage({ imageId });await dcmImage.parse();...
}

修改后:

async function archiveFile(file) {let imageId = "";if (typeof file === "string") {imageId = file;} else {imageId = cornerstoneDICOMImageLoader.wadouri.fileManager.add(file);}const dcmImage = new DCMImage({ imageId });await dcmImage.parse();...
}

總結

本章實現從PACS服務器加載dicom圖像。
說明了對接PACS服務所需的兩個接口的定義和返回數據格式。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/909051.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/909051.shtml
英文地址,請注明出處:http://en.pswp.cn/news/909051.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

STM32+rt-thread判斷是否聯網

一、根據NETDEV_FLAG_INTERNET_UP位判斷 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…

基于React Native開發HarmonyOS 5.0醫療類應用

隨著HarmonyOS 5.0的發布和React Native技術的成熟&#xff0c;開發者現在可以利用React Native框架為HarmonyOS平臺構建高性能的跨平臺醫療應用。 一、技術選型與優勢 1.React Native HarmonyOS的組合優勢 &#xff08;1&#xff09;跨平臺能力??&#xff1a;React Nati…

姜偉生《統計至簡》

姜偉生《統計至簡》 系列叢書之一 這套書圖真漂亮&#xff0c;字間距也大&#xff0c;特別合適直接作為課件。但是理論上弱&#xff0c;有的地方算法也get不點上。適合初學者&#xff0c;因為能看圖說話&#xff1b;又不適合初學者&#xff0c;因為沒有解析、沒有分析。 這學…

滾動—橫向滾動時,如何直接滾動到對應的內容板塊

使用scrollIntoView方法方法解讀 scrollIntoView 是 HTML 元素&#xff08;HTMLElement&#xff09;的一個方法。當調用該方法時&#xff0c;它會嘗試將調用它的元素滾動到瀏覽器的可視區域內。這個方法特別適用于處理頁面上的滾動行為&#xff0c;比如讓用戶能夠快速定位到頁面…

HTML5 定位網頁元素

1. 定位&#xff08;position&#xff09; position&#xff1a;static&#xff08;標準&#xff09; position&#xff1a;relative&#xff08;相對定位&#xff09; 偏移量的方向 相對定位的規律 浮動元素設置相對定位 position&#xff1a;absolute&#xff08;絕對…

分類數據集 - 植物分類數據集下載

數據集介紹&#xff1a;植物分類數據集&#xff0c;真實場景高質量圖片數據&#xff1b;適用實際項目應用&#xff1a;自然場景植物分類項目&#xff0c;以及作為通用分類數據集場景數據的補充&#xff1b;數據集類別&#xff1a;標注說明&#xff1a;采用文件夾來區分不同的目…

?React Hooks 的閉包陷阱問題

這是主包在面試中遇到的一道題目&#xff0c;面試官的問題是&#xff1a;"這個頁面初次展示出來時Count和step的值是什么&#xff0c;我點擊按鈕count和step的值有什么變化&#xff1f;“ 這個題目主包回答的不好&#xff0c;所以想做一個總結。 題目 import React, { …

新基建浪潮下:中國新能源汽車充電樁智慧化建設與管理實踐

在新基建戰略的強力推動下&#xff0c;中國新能源汽車充電樁建設正迎來智慧化升級的重要機遇期。作為連接能源革命與交通革命的關鍵節點&#xff0c;充電基礎設施的智能化轉型不僅關乎新能源汽車產業的可持續發展&#xff0c;更是構建新型電力系統的重要支撐。當前&#xff0c;…

如何在多任務環境中設定清晰的項目優先級?

在多任務環境中設定清晰的項目優先級需要明確項目戰略價值、緊急性、資源利用效率、風險管理。其中&#xff0c;明確項目戰略價值尤為重要&#xff0c;它決定了項目對組織整體戰略目標實現的貢獻程度。例如&#xff0c;戰略價值高的項目&#xff0c;即使不緊急&#xff0c;也應…

【Django】性能優化-普通版

性能優化&#xff1a; 思路 通常無論是什么編程語言或者是什么框架&#xff0c;瓶頸通常都是數據庫相關的操作&#xff1b; 大部分的查詢慢的問題接口都是頻繁查庫、全盤掃描、多層for循環嵌套、高頻查redis、序列化時多級外鍵&#xff1b; 多用O(1)查找復雜度的數據 合理使…

數據治理域——離線數據開發

摘要 文本主要介紹了離線數據開發相關內容,包括業務與流程、阿里MaxCompute系統設計以及阿里調度系統設計。離線數據開發是大數據開發核心組成部分,用于處理批量數據,支持企業多種需求,其流程涵蓋需求調研、數據源接入等環節。阿里MaxCompute系統架構與特點被闡述,調度系…

python-docx 庫教程

Python-docx 庫介紹 官網文檔 python-docx 是一個用于創建和修改 Microsoft Word (.docx) 文件的 Python 庫。它允許你通過編程方式生成格式化的文檔&#xff0c;添加文本、段落、表格、圖片等元素&#xff0c;而無需依賴 Microsoft Word 應用程序。 主要功能 創建新的 Word…

Ansible小試牛刀

注意事項 除了安裝的zabbix相關組件 使用此腳本安裝的所有軟件版本均為系統默認版本 安裝軟件 zabbix相關組件&#xff0c;包括server&#xff0c;agent等 MySQL Redis NGINX openjdk maven nodejs keepalived iptables ipvsadm 使用劇本 --- - hosts: allname…

MCP使用

什么是MCP Model Context Protocol (MCP) 是由 Anthropic 公司于 2024 年 11 月推出的一種開放協議標準&#xff0c;目的在于標準化LLM 與外部數據源、工具及服務之間的交互方式。MCP 被廣泛類比為“AI 領域的 USB-C 接口” MCP與Function Calling的區別 MCP 的核心概念 1.…

邊緣計算一:現代前端架構演進圖譜 —— 從 SPA 到邊緣渲染

過去十年&#xff0c;前端項目架構經歷了從簡單 HTML 文件到復雜框架的飛躍&#xff0c;但很多開發者忽略了**“渲染位置”與“資源交付方式”**對體驗與性能的根本性影響。 從最初的瀏覽器渲染&#xff0c;到現在“在離用戶最近的地方動態返回 HTML”&#xff0c;架構正在悄悄…

linux學習記錄(六)三個常用命令介紹

1.vim命令 Vim是由Vi發展過來的文本編譯器&#xff0c;其代碼補全、編譯及錯誤跳轉等方便編程的功能特別豐富&#xff0c;在程序員中被廣泛使用。 1.1 語法 vim filename 1.2 vi/vim的使用 vi/vim 共分為三種模式&#xff0c;命令模式&#xff08;Command Mode&#xff09;、…

用Python獲取京東關鍵字接口的用戶指南

在電商數據分析和市場研究中&#xff0c;獲取京東平臺的關鍵字搜索結果數據具有重要意義。本文將詳細介紹如何使用Python調用京東開放平臺的API接口&#xff0c;獲取關鍵字相關的商品數據&#xff0c;并進行解析和處理。 一、準備工作 &#xff08;一&#xff09;注冊京東開發…

觀測云,全球領先的監控觀測平臺亮相亞馬遜云科技中國峰會!

觀測云每年都不會缺席亞馬遜云科技峰會 忙完一整季的產品發布&#xff0c;我們終于將目光投向這場全球頂尖的云技術盛會——2025亞馬遜云科技中國峰會。如果你也在這個領域&#xff0c;應該已經感覺到了&#xff1a;這不只是一場大會&#xff0c;而是一個信號。AI、可觀測性、…

消息隊列處理模式:流式與批處理的藝術

&#x1f30a; 消息隊列處理模式&#xff1a;流式與批處理的藝術 &#x1f4cc; 深入解析現代分布式系統中的數據處理范式 一、流式處理&#xff1a;實時數據的"活水" 在大數據時代&#xff0c;流式處理已成為實時分析的核心技術。它將數據視為無限的流&#xff0c;…

一起學習swin-transformer(一)

Transform學習鏈接 從零開始設計Transformer模型&#xff08;1/2&#xff09;——剝離RNN&#xff0c;保留Attention-CSDN博客 Transformer-PyTorch實戰項目——文本分類_transformer文本分類 pytorch-CSDN博客 從零開始設計Transformer模型&#xff08;2/2&#xff09;——…