dicom读取方法-资料

  • 格式:docx
  • 大小:219.16 KB
  • 文档页数:17

Dicom格式文件解析器

学数字图像与通讯,这里讲的暂不涉及通讯那方面的问题 只讲*.dcm 也就是diocm格式文件的读取,读取本身是没啥难度的 无非就是字节码数据流处理。只不过确实比较繁琐。

分析

整体结构先是128字节所谓的导言部分,说俗点就是没啥意义的破数据 跳过就是了,然后是dataElement依次排列的方式 就是一个dataElement接一个dataElement的方式排到文件结尾 通俗的讲dataElement就是指tag 就是破Dicom标准里定义的数据字典。tag是4个字节表示的 前两字节是组号后两字节是偏移号 比如0008,0018。所有dataElement在文件中都是按tag排序的

比如0002,0001 0002,0002 0003,0011

文件整体结构如下:

又把论文里的这图贴上来 总结的很好。单个dataElement的结构如下:

显示VR:VR为OB OW OF UT SQ UN的元素结构

组号 元素号 VR 预留 值长度 数据元素值

2 2 2 2(0x00,0x00) 4 由数据长度决定

显示VR:VR为普通类型时元素结构(少了预留那一行)

组号 元素号 VR 值长度 数据元素值

2 2 2 4 由数据长度决定

隐式VR 时元素结构

组号 元素号 值长度 数据元素值

2 2 4 由数据长度决定

要问VR是啥东东 ,值表示法 啥叫值表示法啊 俺不懂 int string short

ushort 懂不 就是这个意思,Dicom标准真坑爹 非要整个怪怪的概念。

VR总共27个 跟c#值类型对应关系我都写好了:

1 string getVF(string VR, byte[] VF)

2 {

3 string VFStr = string.Empty;

4 switch (VR)

5 {

6 case "SS":

7 VFStr = BitConverter.ToInt16(VF, 0).ToString();

8 break;

9 case "US":

10 VFStr = BitConverter.ToUInt16(VF, 0).ToString();

11

12 break;

13 case "SL":

14 VFStr = BitConverter.ToInt32(VF, 0).ToString();

15

16 break;

17 case "UL":

18 VFStr = BitConverter.ToUInt32(VF, 0).ToString();

19

20 break;

21 case "AT":

22 VFStr = BitConverter.ToUInt16(VF, 0).ToString();

23

24 break;

25 case "FL":

26 VFStr = BitConverter.ToSingle(VF, 0).ToString();

27

28 break;

29 case "FD":

30 VFStr = BitConverter.ToDouble(VF, 0).ToString();

31

32 break;

33 case "OB":

34 VFStr = BitConverter.ToString(VF, 0);

35 break;

36 case "OW":

37 VFStr = BitConverter.ToString(VF, 0); 38 break;

39 case "SQ":

40 VFStr = BitConverter.ToString(VF, 0);

41 break;

42 case "OF":

43 VFStr = BitConverter.ToString(VF, 0);

44 break;

45 case "UT":

46 VFStr = BitConverter.ToString(VF, 0);

47 break;

48 case "UN":

49 VFStr = Encoding.Default.GetString(VF);

50 break;

51 default:

52 VFStr = Encoding.Default.GetString(VF);

53 break;

54 }

55 return VFStr;

56 }

找个dicom文件在十六进制编辑器下瞧瞧 给你整明白:

所有dataElement从前到后按tag又可简单分段:

文件元dataElement 不受传输语法影响 总是以显示VR方式表示 因为它里面就定义了传输语法

普通dataElement 受传输语法影响 显示VR表示方式还是隐式VR表示方式 像素数据dataElement 最重要也是最大的一个数据项 其实存储的就是图像数据

几个特殊的tag很重要 前面说过了tag就是dicom里定义的字典。文件元dataElement 和跟像素数据相关的dataElement 都很重要,其他的很多 如果全部照顾完的话估计得写上千行switch语句吧,所以没有必要一般我们一般只抓取关键的tag。并且在隐式语法下要确定VR也必须根据字典来确定

关键的tag如下:

1 string getVR(string tag)

2 {

3 switch (tag)

4 {

5 case "0002,0000"://文件元信息长度

6 return "UL";

7 break;

8 case "0002,0010"://传输语法

9 return "UI";

10 break;

11 case "0002,0013"://文件生成程序的标题

12 return "SH";

13 break;

14 case "0008,0005"://文本编码

15 return "CS";

16 break;

17 case "0008,0008":

18 return "CS";

19 break;

20 case "0008,1032"://成像时间

21 return "SQ";

22 break;

23 case "0008,1111":

24 return "SQ";

25 break;

26 case "0008,0020"://检查日期

27 return "DA";

28 break;

29 case "0008,0060"://成像仪器

30 return "CS";

31 break;

32 case "0008,0070"://成像仪厂商

33 return "LO"; 34 break;

35 case "0008,0080":

36 return "LO";

37 break;

38 case "0010,0010"://病人姓名

39 return "PN";

40 break;

41 case "0010,0020"://病人id

42 return "LO";

43 break;

44 case "0010,0030"://病人生日

45 return "DA";

46 break;

47 case "0018,0060"://电压

48 return "DS";

49 break;

50 case "0018,1030"://协议名

51 return "LO";

52 break;

53 case "0018,1151":

54 return "IS";

55 break;

56 case "0020,0010"://检查ID

57 return "SH";

58 break;

59 case "0020,0011"://序列

60 return "IS";

61 break;

62 case "0020,0012"://成像编号

63 return "IS";

64 break;

65 case "0020,0013"://影像编号

66 return "IS";

67 break;

68 case "0028,0002"://像素采样1为灰度3为彩色

69 return "US";