DICOM图像知识:DICOM图像排序与坐标系解析

目录

引言

1. 概述

2. DICOM图像排序规则

2.1 Patient的Study按Study Date排序

2.2 Study的Series按Series Number排序

2.3 Series的SOP按Instance Number或Slice Location排序

2.3.1 Instance Number排序

2.3.2 Slice Location排序

2.3.3 使用Image Position (Patient)和Image Orientation (Patient)

3. DICOM坐标系与相关元数据

3.1 DICOM坐标系概述

3.2 Image Position (Patient)和Image Orientation (Patient)

3.2.1 Image Position (Patient)

3.2.2 Image Orientation (Patient)

4. 实际应用与示例

4.1 示例排序流程

4.2 C++实现示例

注意事项

5. 总结


引言

医学影像在临床诊断和研究中发挥着至关重要的作用,而DICOM(数字成像和通信医学)标准是目前存储和传输医学影像的主要方式。在DICOM中,图像的排序对于正确理解和分析患者的影像数据至关重要。本文将详细探讨DICOM图像的排序规则,以及相关的坐标系和元数据的含义。

1. 概述

DICOM标准用于存储和传输医学影像数据,并包含复杂的层次结构。影像数据通常以Patient、Study、Series和SOP(Service-Object Pair)四级结构组织。为了正确地展示和分析这些影像数据,我们需要遵循特定的排序规则。

2. DICOM图像排序规则

2.1 Patient的Study按Study Date排序

在DICOM中,每个Patient(患者)可以有多个Study(研究/检查)。为了理清时间顺序,通常按Study Date(0020,0008)对这些Study进行排序:

  • Study Date:表示Study的日期,格式为YYYYMMDD。
  • 排序方法:按时间顺序从早到晚排列。

这种排序方式有助于医疗人员查看患者的病史和随访过程。

2.2 Study的Series按Series Number排序

每个Study通常包含多个Series(序列),每个Series可以代表不同的成像技术或参数设置。Series按Series Number(0020,0011)排序:

  • Series Number:一个整数,标识同一Study下的不同Series。
  • 排序方法:按Series Number的数值升序排列。

Series Number可以帮助区分同一Study下的不同影像序列,如不同的MRI序列或不同的CT扫描相位。

2.3 Series的SOP按Instance Number或Slice Location排序

在每个Series中,有多个SOP实例,通常对应一系列切片图像。常用的排序依据有:

2.3.1 Instance Number排序
  • Instance Number (0020,0013):表示影像在Series中的顺序,通常用于初步排序。
  • 排序方法:按Instance Number的数值升序排列。
2.3.2 Slice Location排序
  • Slice Location (0020,1041):表示切片在病人体内的位置,通常用于更精确的排序。
  • 排序方法:按Slice Location数值升序排列。
2.3.3 使用Image Position (Patient)和Image Orientation (Patient)

当Instance Number和Slice Location不足以反映切片的正确顺序时,可以使用Image Position (Patient)和Image Orientation (Patient)进行排序:

  • Image Position (Patient) (0020,0032):表示图像左上角像素在患者体坐标系中的位置,通常为三个坐标值 (x, y, z)。
  • Image Orientation (Patient) (0020,0037):表示图像行和列的方向向量,通常为六个值,前三个表示行方向,后三个表示列方向。

排序方法:

  1. 根据Image Orientation确定主要的切片方向(轴向、矢状或冠状)。
  2. 在主要方向上,使用Image Position的值进行排序。

3. DICOM坐标系与相关元数据

3.1 DICOM坐标系概述

DICOM坐标系基于患者体坐标系,通常定义如下:

  • X轴:从患者左侧到右侧,左为负,右为正。
  • Y轴:从患者背部到腹部,背为负,腹为正。
  • Z轴:从患者脚到头,脚为负,头为正。

这种坐标系有助于标准化不同设备和厂家生成的影像数据。

3.2 Image Position (Patient)和Image Orientation (Patient)

3.2.1 Image Position (Patient)
  • 含义:图像左上角像素在患者体坐标系中的三维位置。
  • 用途:用于确定图像在三维空间中的绝对位置,特别是在多切片排序和重建中。
3.2.2 Image Orientation (Patient)
  • 含义:描述图像行和列在患者体坐标系中的方向。
  • 用途:用于确定图像的拍摄角度和方向,确保不同扫描间的对齐。

Image Orientation提供了两个向量,分别表示图像的行和列方向。例如,[1, 0, 0, 0, 1, 0]表示标准轴向切片,其行方向为X轴正方向,列方向为Y轴正方向。

4. 实际应用与示例

4.1 示例排序流程

假设我们有一个患者的DICOM影像数据集,包含不同的Study、Series和SOP。排序流程如下:

  1. 按Study Date排序Study:将所有Study按日期升序排列。
  2. 按Series Number排序Series:在每个Study中,对其包含的Series按Series Number排序。
  3. 按Image Position (Patient)排序SOP:在每个Series中,根据Image Orientation判断主要方向,并使用Image Position进行排序。

4.2 C++实现示例

下面是一个简单的C++示例,使用DCMTK库对DICOM文件进行排序:

#include <dcmtk/dcmdata/dctk.h>
#include <dcmtk/dcmimgle/dcmimage.h>
#include <iostream>
#include <vector>
#include <algorithm>// 定义一个结构体来存储DICOM信息
struct DicomInfo {DcmDataset* dataset;std::string studyDate;int seriesNumber;float imagePosition[3];
};// 比较函数:用于按Study Date排序
bool compareByStudyDate(const DicomInfo& a, const DicomInfo& b) {return a.studyDate < b.studyDate;
}// 比较函数:用于按Series Number排序
bool compareBySeriesNumber(const DicomInfo& a, const DicomInfo& b) {return a.seriesNumber < b.seriesNumber;
}// 比较函数:用于按Image Position排序(假设Z轴为主要方向)
bool compareByImagePosition(const DicomInfo& a, const DicomInfo& b) {return a.imagePosition[2] < b.imagePosition[2];
}int main() {const char* dicomDirectory = "path/to/dicom/files";std::vector<DicomInfo> dicomFiles;// 遍历目录并读取DICOM文件DcmFileFormat fileFormat;DcmDirInterface dicomDir(dicomDirectory);if (dicomDir -> isGood()) {const DcmDirectoryRecord* record = dicomDir -> getFirstRecord();while (record != NULL) {OFString fileName;if (record -> findAndGetOFString(DCM_ReferencedFileID, fileName).good()) {if (fileFormat.loadFile(fileName.c_str()).good()) {DcmDataset* dataset = fileFormat.getDataset();DicomInfo info;dataset -> findAndGetOFString(DCM_StudyDate, info.studyDate);dataset -> findAndGetSint32(DCM_SeriesNumber, info.seriesNumber);dataset -> findAndGetFloat32Array(DCM_ImagePositionPatient, info.imagePosition);info.dataset = dataset;dicomFiles.push_back(info);}}record = dicomDir -> getNextRecord();}}// 排序std::sort(dicomFiles.begin(), dicomFiles.end(), compareByStudyDate);std::sort(dicomFiles.begin(), dicomFiles.end(), compareBySeriesNumber);std::sort(dicomFiles.begin(), dicomFiles.end(), compareByImagePosition);// 输出排序结果for (const auto& dicom : dicomFiles) {std::cout << "Study Date: " << dicom.studyDate<< ", Series Number: " << dicom.seriesNumber<< ", Image Position: (" << dicom.imagePosition[0] << ", "<< dicom.imagePosition[1] << ", " << dicom.imagePosition[2] << ")" << std::endl;}return 0;
}

注意事项

  • DCMTK库提供了强大的DICOM文件操作能力,但使用时需注意DICOM数据的完整性和有效性。
  • 在使用DCMTK库时,请确保安装并配置库路径,以便编译和链接正确。

5. 总结

        DICOM图像的排序是医学影像分析中的基础步骤,确保了影像的连贯性和准确性。通过理解和应用DICOM的相关元数据,尤其是坐标系信息,可以有效地对影像进行排序和定位。这种排序不仅适用于临床诊断中的影像查看,也为后续的三维重建和影像分析打下坚实基础。理解DICOM的坐标系和元数据,将有助于更好地解析和应用影像数据。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/58878.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Js — 定时器

有两种&#xff1a;setInterval 和 setTimeout 间隔时间单位为毫秒 setInterval 每隔指定的毫秒数重复执行一个函数或代码 开启定时器&#xff1a;setInterval(函数&#xff0c;间隔时间) 作用&#xff1a;每隔一段时间调用这个函数 注意&#xff1a;它不是立即执行&#x…

其他教程:如何设计一个App扫码登录功能,来实现免账号密码登录功能,仅供参考

–本次教程是给大家列举一下常见的扫码登录功能&#xff0c;小程序或app均可参考&#xff0c;如需更安全的模式可多次设计加工&#xff0c;本次只列举概念层面的实现方式

ChatGPT键盘快捷键(按ctrl + /呼出)

文章目录 ChatGPT键盘快捷键- 打开新聊天: Ctrl Shift O- 聚焦聊天输入: Shift Esc- 复制最后一个代码块: Ctrl Shift ;- 复制最后一个回复: Ctrl Shift C- 设置自定义指令: Ctrl Shift I- 切换边栏: Ctrl Shift S- 删除聊天: Ctrl Shift ⌫- 显示快捷方式: Ctrl …

AWTK-HarmonyOS NEXT 发布

AWTK 全称为 Toolkit AnyWhere&#xff0c;是 ZLG 倾心打造的一套基于 C 语言开发的 GUI 框架。旨在为用户提供一个功能强大、高效可靠、简单易用、可轻松做出炫酷效果的 GUI 引擎&#xff0c;支持跨平台同步开发&#xff0c;一次编程&#xff0c;到处编译&#xff0c;跨平台使…

【开发】Java的内存溢出

Java之内存溢出 Java之内存溢出 | OutOfMemoryError 我们都知道&#xff0c;在Java的世界里&#xff0c;由JVM管理着Java中的“垃圾对象”&#xff0c;也就是不被引用的对象&#xff1b;当一个对象不被其它对象引用的时候&#xff0c;该对象就会被垃圾回收器清理掉。但是在某些…

EasyExcel的AbstractColumnWidthStyleStrategy注入CellStyle不生效

设置背景色 CellStyle style workbook.createCellStyle();style.setFillForegroundColor(IndexedColors.RED.getIndex()); // 是设置前景色不是背景色style.setFillPattern(FillPatternType.SOLID_FOREGROUND)EasyExcel.writerTable(0).head(Head1.class).registerWriteHandl…

【51单片机】LED点阵屏 原理 + 使用

学习使用的开发板&#xff1a;STC89C52RC/LE52RC 编程软件&#xff1a;Keil5 烧录软件&#xff1a;stc-isp 开发板实图&#xff1a; 文章目录 LED点阵屏显示原理74HC595 编码LED点阵屏显示笑脸LED点阵屏显示动画 LED点阵屏 点阵屏在开发板的右上角&#xff0c;注意使用前需要…

深度学习-张量相关

一. 张量的创建 张量简介 张量是pytorch的基本数据结构 张量&#xff0c;英文为Tensor&#xff0c;是机器学习的基本构建模块&#xff0c;是以数字方式表示数据的形式。 例如&#xff0c;图像可以表示为形状为 [3, 224, 224] 的张量&#xff0c;这意味着 [colour_channels, h…

使用vite构建一个react网站,并部署到Netlify上

这篇教程中&#xff0c;我会教你如何用vite快速构建一个react网站&#xff0c;并把网站免费部署到Netlify上&#xff0c;让别人可以经由网址访问你的react网站。 1. 使用vite构建基础框架 npm create vitelatestcd vite-project npm install npm run dev2. 网站内容设计 3. 构…

Fastify Swagger:自动化API文档生成与展示

在现代软件开发中&#xff0c;API文档的生成和维护是一个不可或缺的环节。Fastify Swagger 是一个专为 Fastify 框架设计的插件&#xff0c;它能够自动生成符合 Swagger&#xff08;OpenAPI v2 或 v3&#xff09;规范的文档&#xff0c;从而帮助开发者轻松创建和维护API文档。本…

【网络原理】万字详解 UDP 和 TCP

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. UDP1.1 UDP 报文格式1.1.1 源端口/目的端口1.1.2 报文长度1.1.3 校验和 2. TCP2.1 TCP 报文结构2.2 TCP 特…

Go 中的泛型,日常如何使用

泛型从 go 的 1.18 开始支持 什么是泛型编程 在泛型出现之前&#xff0c;如果需要计算两数之和&#xff0c;可能会这样写&#xff1a; func Add(a, b int) int {returb a b } 这个很简单&#xff0c;但是只能两个参数都是 int 类型的时候才能调用 如果想要计算两个浮点数…

IoTDB 与 HBase 对比详解:架构、功能与性能

五大方向&#xff0c;洞悉 IoTDB 与 HBase 的详尽对比&#xff01; 在物联网&#xff08;IoT&#xff09;领域&#xff0c;数据的采集、存储和分析是确保系统高效运行和决策准确的重要环节。随着物联网设备数量的增加和数据量的爆炸式增长&#xff0c;开发者和决策者们需要选择…

单片机串口接收状态机STM32

单片机串口接收状态机stm32 前言 项目的芯片stm32转国产&#xff0c;国产芯片的串口DMA接收功能测试不通过&#xff0c;所以要由原本很容易配置的串口空闲中断触发DMA接收数据的方式转为串口逐字节接收的状态机接收数据 两种方式各有优劣&#xff0c;不过我的芯片已经主频跑…

词嵌入方法(Word Embedding)

词嵌入方法&#xff08;Word Embedding&#xff09; Word Embedding是NLP中的一种技术&#xff0c;通过将单词映射到一个空间向量来表示每个单词 ✨️常见的词嵌入方法&#xff1a; &#x1f31f;Word2Vec&#xff1a;由谷歌提出的方法&#xff0c;分为CBOW&#xff08;conti…

【go从零单排】实现枚举类型(Enum)

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 在Go语言中&#xff0c;并没有内置的枚举类型&#xff08;Enum&#xff09;&…

Python爬虫如何处理验证码与登录

Python爬虫如何处理验证码与登录 Python 爬虫在抓取需要登录的网站数据时&#xff0c;通常会遇到两个主要问题&#xff1a;登录验证和验证码处理。这些机制是网站用来防止自动化程序过度抓取数据的主要手段。本文将详细讲解如何使用 Python 处理登录与验证码&#xff0c;以便进…

MOS管损坏原因

MOS管是什么&#xff1f; MOS管&#xff0c;全程就是MOSFET&#xff08;Metal-Oxide-Semiconductor Field-Effect Transistor&#xff09;&#xff0c;是一种场效应晶体管。‌ MOS管控制原理 MOS管的工作原理是通过栅极电压&#xff08;G&#xff09;来控制源极&#xff08…

「QT」QT5程序设计专栏目录

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid…

论文阅读《机器人状态估计中的李群》

目录 摘要1 介绍2 微李理论2.1 李群 摘要 李群是一个古老的数学抽象对象&#xff0c;可以追溯到19世纪&#xff0c;当时数学家 Sophus Lie奠定了连续变换群理论的基础。多年后&#xff0c;它的影响已经蔓延到科学和技术的各个领域。在机器人领域&#xff0c;我们最近正在经历一…