dicom, i wrote this article, need some advice

FooSleeper 2002-06-20 02:52:40
3. DICOM Part 10文件的定义
一个文件包含一个SOP实例,相应的,就由许多Attribute组成。但在文件中,这样一个SOP实例被称为Data Set,它是SOP的一个较低层次的抽象。Data Set是Data Element的集合,自然的Data Element就是Attribute的一个较低层次的抽象。

图3-1 每个DICOM文件包含一个SOP Instance
3.1. 构成文件的元素
Attribute是对事物的特征的在对象层次上的抽象,它的对应物Data Element则是在二进制的级别对这些特征的表达,Data Element侧重于数据的二进制结构,它可以直接被编码进文件的输入输出流。简单的说,一个Data Element就是一个编码过的IOD的Attribute。那我们就在这样的一个“物理”层次考察Data Element的结构。

图3-2 Data Set和Data Element的结构
一个Data Element由下面几部分组成:
Tag是Element的标识符,由两部分组成:Group和Element,Group是Element的集合。如(0002,0010)表示Group 0002 File Meta Information中的Transfer Syntax UID(0010)这个Element。Part 6 Data Dictionary 给出了编码与表示的意义的对应关系。
Value Representation(VR)在Part 5中定义。同样的一串十六进制数可能表示字符、浮点数、整数等等,这种歧义性由VR来消除,并且VR限制了Data域中可以存在的字符,如DS这个VR表示Decimal String,即限制了只能取“0”-”9”,“+”,“-”,“E”,“e”,“.”。并且,DS限制了Data域的长度最大为16字节。VR有两种:显式(Explicit)的和隐式(Implicit)的。隐式的VR意味着没有VR域。并且,OB、OW、SQ、UN四种VR是4字节长度,其他的VR为2字节。简单的说,VR就是数据类型。
Value Length 给出Data域的长度,以字节为单位。这个长度不可以超过该VR允许的最大长度。
若VR域为4字节,则VL域也为4字节;若VR域为2字节,VL域也为2字节。如果是隐式(Implicit)VR,则VL长为4字节。
Data 域的长度为VL域的值,域中的数据必须符合VR的要求。
于是Element的结构如下:

图3-3 Data Element的几种结构
我们解码和编码文件时直接和Data Element打交道,因此其结构需要特别注意。
3.2. 文件的头部
DICOM文件的头部称作File Meta Information,它包含了文件所封装的数据集的识别信息。每个DICOM文件都应该有一个Meta File Information。
我们来考察Meta File Information 的结构。
首先是128字节固定长度的File Preamble,这是给完成特定功能的应用程序使用的,在DICOM的这一部分对File Preamble的结构和内容并无任何要求,因此我们可以安全的忽略它。在特定实现中,如果没有使用File Preamble,应该把全部128字节都设为00H。
随后是4字节的DICOM文件前缀(DICOM Prefix),这四个字节依次是“D”、“I”、“C”、“M”四个字符,它们表示这是一个DICOM文件。我们就依靠这四个字节来识别DICOM文件。
File Preamble和DICOM Prefix都没有结构化成带Tag和长度的Data Element的形式。
随后是属于Group 0002 File Meta Information的Data Element。其中只有0002,0010 Transfer Syntax UID是我们关心的,其他的都可以忽略。
3.3. 通信前的协商—Transfer Syntax
0002,0010 Transfer Syntax UID唯一标识了后续数据的编码方法。下表列出可能的取值
Transfer Syntax UID 说明
Native 1.2.840.10008.1.2 Implicit VR, Little Endian
1.2.840.10008.1.2.1 Explicit VR, Little Endian
1.2.840.10008.1.2.2 Explicit VR, Big Endian
JPEG 1.2.840.10008.1.2.4.50 ~ 70 JPEG有多种编码方法,相应的有多个Transfer Syntax UID,详见Part 5 Annex A
JPEG-LS 1.2.840.10008.1.2.4.80 Lossless,这两种JPEG-LS的图像采用ISO/IS-14495-1 (JPEG-LS Part 1)的静态图像压缩方法
1.2.840.10008.1.2.4.81 Near-Lossless
RLE 1.2.840.10008.1.2.5 Run Length Encoding, Lossless
表3-4 常见的Transfer Syntax UID
将一个文件视为SOP,将读取它的程序视为应用程序实体(Application Entity),那么这个读取的过程可以看作两个对象间的通信,只有当双方就数据编码方法有一致的协议时,通信(读文件)才能正常进行,Transfer Syntax就是它们的通信协议。
从上表可以清楚看到,Transfer Syntax,即通信双方协商的内容,包括字节顺序,VR的显隐,数据是否压缩及压缩的方法。其中Explicit VR Little Endian Transfer Syntax(UID = 1.2..840.10008.1.2.1)是DICOM标准默认的。
JPEG压缩的DICOM文件,事实上只是将普通DCT编码的JPEG文件嵌套进Data Element里去。
JPEG-LS的两种压缩方法中,Lossless方法采用差分编码,这种压缩方法是无损的,但是效率非常的低。Near-Lossless方法有较高的效率,但局限于12位的图像。
RLE也是一种常见的压缩方法,DICOM采用的RLE并无任何特别之处。
3.4. 一个Part 10文件的样本
我们直接观察文件的二进制编码。下图中标出了两个Data Element的完整编码,

图3-5 样本图像的字节流
4. 文件的解码
文件的解码过程如下:
解析文件的头部,因为标准要求头部总用DICOM的默认Transfer Syntax,即Implicit VR Little Endian Transfer Syntax (UID = “1.2.840.10008.1.2”),因此读取头部不存在协商Transfer Syntax的问题。解析头部后得到我们最关心的Transfer Syntax。
随后遍历文件,解析每一个Data Element,得到一系列的属性值,保存在容器中。
查看我们得到的一系列Data Element,此时不妨将它们称作Attribute,因为如果把我们将要构造的图像视为对象,它们就是这个图像的属性了。
根据各属性构造出我们的图像,解码过程就完成了。
4.1. 文件格式识别
识别一个DICOM文件,我们只需简单的检查128字节后面的四个字节是否是DICM四个字符。这四个字符都是大写,采用ISO 8859 G0编码,等价于我们常用的ASCII。
在特定的上下文环境中,如来自同一厂商的一套机器之间的通信,由于这些机器之间通常对如何通信(即数据的编码规则)有一致的约定,因而省略File Meta Information是可以接受的。这种省略了File Meta Information的文件习惯称之为裸(Raw)文件。并且,在早期的ACR-NEMA标准的文件中,也不存在File Meta Information。虽然标准中定义了每个DICOM格式的文件都必须有File Meta Information,但是这种省略头部的情形十分普遍,因而我们必须为此提供足够的灵活性。
考察DICOM文件,可以发现去掉了File Meta Information,文件将总是以(0008,00xx)开头,我们可以据此判断一个Raw或ACR-NEMA文件。这种方法并不完美,但至少是有效的。并且,我们假设这些文件使用DICOM的默认Transfer Syntax,即Implicit VR Little Endian Transfer Syntax (UID = “1.2.840.10008.1.2”),这通常是合理的。
4.2. 遍历文件的元素
一个Data Element总是紧挨着另一个,Data Element本身又包含了它自身的长度,所以Data Element的边界总能分的清清楚楚,因此这样一个遍历的过程没有什么困难。需要注意的是上文提到的VR和VL的不同情况,避免算错Data Element的长度。
读出来的Data Element我们把它“变回”Attribute——通过在Part 6定义的数据字典中查找,得到一个名称——值对。对于Implicit VR的文件我们也只能用这种方法得知它的VR。这种方法要求我们有一个完整的数据字典,才能保证顺利完成解码。对一些私有的Data Element(它们的Group号是奇数,很好辨认),如果没有它们的数据字典,我们将无能为力。
有时可能需要根据VR解析Data Element的值,比如DS(Decimal String)转换成整数。这种麻烦事我们还是尽量将它交给用户(人或程序)决定。因此最好把VR也作为Attribute的一部分,将Data Element的值原样输出,将转换的决定权交给用户。
因为标准允许Data Element的嵌套,因此一个完善的实现应该能够递归遍历。
4.3. 解释像素数据
首先介绍我们将要用到的Data Element,这些和图像有关的属性几乎都属于Group 0028。
Sample Per Pixel(0028,0002)
这个属性表示每像素包含的采样数,典型的RGB为3,CMYK为4,灰度为1,HSV为3……和常用的色彩通道这个词的意义似乎差不多。
Photometric Interpretation(0028,0004)
这个属性直接说明了图像的色彩空间。常见的值有:MONOCHROME1:灰度图像,象素最小值显示为白色;MONOCHROME2:灰度图像,象素最小值显示为黑色;RGB:RGB彩色图像;HSV:HSV彩色图像;PALLETE COLOR:使用调色板的彩色图像。此外还有ARGB、CMYK、YBR-FULL等。我们构造的图像也要使用同样的色彩空间。这个属性和Sample Per Pixel合起来限制了图像的色彩。
Planar Configuration (0028,0006)
Planar Configuration 指明了彩色图像的象素数据的排列顺序。显然当Sample Per Pixel (0028,0002) 有大于1的值时这个属性才有意义,否则,不该出现。这个属性有两种取值:
0000 第一个象素的样本值后面接着第二个象素样本值,等等。对RGB图象, 这意味着被发送的象素数据的顺序是R1,G1,B1,R2,B2,G2,……,等等。HSV、CMYK等类似。
0001 每个颜色位面应该被连续发送。对RGB图象,这意味着被发送的象素值的顺序是R1,R2,R3,……,G1,G2,G3,……,B1,B2,B3,等等。其他彩色图像类似。
Number Of Frames(0028,0008)
图像的帧数,单帧图像是没有这个属性的。
Rows(0028,0010)
图像的高(以像素为单位)。
Columns(0028,0011)
图像的宽(以像素为单位)。
Bits Allocated(0028,0100)
Bits Stored(0028,0101)
High Bit(0028,0102)
这三个属性描述了像素单元的存储结构

图4-1 像素单元的存储结构
我们再来看看像素数据。
像素数据存储在Pixel Data(7FE0,0010)。
解释这些像素数据首先要将一个个像素区分开来。Bits Allocated和Sample Per Pixel就定义了像素的边界。例如Bits Allocated等于16,Sample Per Pixel等于1,那么16×1 = 16 bit = 2 字节,即每个像素占2字节,于是我们把像素数据2字节2 字节分开。又如Bits Allocated
...全文
200 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
FooSleeper 2002-06-23
  • 打赏
  • 举报
回复
稍后我会加上彩色(用LUT的)和压缩的内容,不过JPEG Lossless我自己还没看完。
建议看看comp.protocols.dicom,我想你的问题都能找到答案,直接在google上搜就行。
FooSleeper 2002-06-23
  • 打赏
  • 举报
回复
foosleeper@163.net
sxychee 2002-06-20
  • 打赏
  • 举报
回复
我现在搞这个,不过图像的处理我做了很简单的,读单色的,所以好多问题还想请教你,尤其的彩色和压缩的解析。我现在在做SCP和SCU还没出来!!!
QQ:36149522
MAIL:sxychee@163.com

4,445

社区成员

发帖
与我相关
我的任务
社区描述
图形图像/机器视觉
社区管理员
  • 机器视觉
  • 迪菲赫尔曼
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧