1 / 17
文档名称:

dicom读取方法-资料.docx

格式:docx   大小:145KB   页数:17页
下载后只包含 1 个 DOCX 格式的文档,没有任何的图纸或源代码,查看文件列表

如果您已付费下载过本站文档,您可以点这里二次下载

分享

预览

dicom读取方法-资料.docx

上传人:帅气的小哥哥 2024/5/12 文件大小:145 KB

下载得到文件列表

dicom读取方法-资料.docx

相关文档

文档介绍

文档介绍:该【dicom读取方法-资料 】是由【帅气的小哥哥】上传分享,文档一共【17】页,该文档可以免费在线阅读,需要了解更多关于【dicom读取方法-资料 】的内容,可以使用淘豆网的站内搜索功能,选择自己适合的文档,以下文字是截取该文章内的部分文字,如需要获得完整电子版,请下载此文档到您的设备,方便您编辑和打印。格式文件解析器学数字图像与通讯,这里讲的暂不涉及通讯那方面的问题只讲*.dcm也就是diocm格式文件的读取,读取本身是没啥难度的无非就是字节码数据流处理。只不过确实比较繁琐。分析整体结构先是128字节所谓的导言局部,说俗点就是没啥意义的破数据跳过就是了,标准里定义的数据字典。tag是4个字节表示的前两字节是组号后两字节是偏移号比方0008,0018。所有dataElement在文件中都是按tag排序的比方0002,0001?0002,0002?0003,0011文件整体结构如下:又把论文里的这图贴上来总结的很好。单个dataElement的结构如下:显示VR:VR为OB?OW?OF?UT?SQ?UN的元素结构组号元素号VR预留值长度数据元素值2222〔0x00,0x00〕4由数据长度决定显示VR:VR为普通类型时元素结构〔少了预留那一行〕组号元素号VR值长度数据元素值2224由数据长度决定隐式VR?时元素结构组号元素号值长度数据元素值224由数据长度决定?要问VR是啥东东,值表示法啥叫值表示法啊俺不懂intstringshortushort懂不就是这个意思,标准真坑爹非要整个怪怪的概念。VR总共27个跟c#值类型对应关系我都写好了:1stringgetVF(stringVR,byte[]VF)2{3stringVFStr=;4switch(VR)5{6case"SS":7VFStr=(VF,0).ToString();8break;9case"US":10VFStr=(VF,0).ToString();1112break;13case"SL":14VFStr=(VF,0).ToString();1516break;17case"UL":18VFStr=(VF,0).ToString();1920break;21case"AT":22VFStr=(VF,0).ToString();2324break;25case"FL":26VFStr=(VF,0).ToString();2728break;29case"FD":30VFStr=(VF,0).ToString();3132break;33case"OB":34VFStr=(VF,0);35break;36case"OW":37VFStr=(VF,0);38break;39case"SQ":40VFStr=(VF,0);41break;42case"OF":43VFStr=(VF,0);44break;45case"UT":46VFStr=(VF,0);47break;48case"UN":49VFStr=(VF);50break;51default:52VFStr=(VF);53break;54}55returnVFStr;56}文件在十六进制编辑器下瞧瞧给你整明白:所有dataElement从前到后按tag又可简单分段:文件元dataElement不受传输语法影响总是以显示VR方式表示?因为它里面就定义了传输语法普通dataElement受传输语法影响显示VR表示方式还是隐式VR表示方式像素数据dataElement最重要也是最大的一个数据项其实存储的就是图像数据里定义的字典。文件元dataElement和跟像素数据相关的dataElement都很重要,其他的很多如果全部照顾完的话估计得写上千行switch语句吧,所以没有必要一般我们一般只抓取关键的tag。并且在隐式语法下要确定VR也必须根据字典来确定关键的tag如下:1stringgetVR(stringtag)2{3switch(tag)4{5case"0002,0000"://文件元信息长度6return"UL";7break;8case"0002,0010"://传输语法9return"UI";10break;11case"0002,0013"://文件生成程序的标题12return"SH";13break;14case"0008,0005"://文本编码15return"CS";16break;17case"0008,0008":18return"CS";19break;20case"0008,1032"://成像时间21return"SQ";22break;23case"0008,1111":24return"SQ";25break;26case"0008,0020"://检查日期27return"DA";28break;29case"0008,0060"://成像仪器30return"CS";31break;32case"0008,0070"://成像仪厂商33return"LO";34break;35case"0008,0080":36return"LO";37break;38case"0010,0010"://病人姓名39return"PN";40break;41case"0010,0020"://病人id42return"LO";43break;44case"0010,0030"://病人生日45return"DA";46break;47case"0018,0060"://电压48return"DS";49break;50case"0018,1030"://协议名51return"LO";52break;53case"0018,1151":54return"IS";55break;56case"0020,0010"://检查ID57return"SH";58break;59case"0020,0011"://序列60return"IS";61break;62case"0020,0012"://成像编号63return"IS";64break;65case"0020,0013"://影像编号66return"IS";67break;68case"0028,0002"://像素采样1为灰度3为彩色69return"US";70break;71case"0028,0004"://图像模式MONOCHROME2为灰度72return"CS";73break;74case"0028,0010"://row高75return"US";76break;77case"0028,0011"://col宽78return"US";79break;80case"0028,0100"://单个采样数据长度81return"US";82break;83case"0028,0101"://实际长度84return"US";85break;86case"0028,0102"://采样最大值87return"US";88break;89case"0028,1050"://窗位90return"DS";91break;92case"0028,1051"://窗宽93return"DS";94break;95case"0028,1052":96return"DS";97break;98case"0028,1053":99return"DS";100break;101case"0040,0008"://文件夹标签102return"SQ";103break;104case"0040,0260"://文件夹标签105return"SQ";106break;107case"0040,0275"://文件夹标签108return"SQ";109break;110case"7fe0,0010"://像素数据开始处111return"OW";112break;113default:114return"UN";115break;116}117}?最关键的两个tag:0002,0010普通tag的读取方式little字节序还是big字节序?隐式VR还是显示VR。由它的值决定1switch(VFStr)2{3case"\0"://显示little4isLitteEndian=true;5isExplicitVR=true;6break;7case"\0"://显示big8isLitteEndian=false;9isExplicitVR=true;10break;11case"\0"://隐式little12isLitteEndian=true;13isExplicitVR=false;14break;15default:16break;17}7fe0,0010像素数据开始处整理格式文件的过程已经很清晰了吧第一步:跳过128字节导言局部,并读取"DICM"格式文件第二步:读取第一局部也就是非常重要的文件元dataElement。读取所有0002开头的tag并根据0002,0010的值确定传输语法。文件元tag局部的数据元素都是以显示VR的方式表示的读取它的值也就是字节码处理别告诉我说你不会字节码处理哈。传输语法说得那么官方,你就忽悠吧其实就确定两个东西而已1字节序这个根本上都是little字节序。举个例子吧十进制数35280用十六进制表示是0xff00?但是存储到文件中你用十六进制编辑器翻开你看到的是这个样子00ff这就是little字节序。平常我们用的x86PC在windows下都是little字节序包括AMD的CPU。别太较真较真的话这个问题又可以写篇博客了。2确定从0002以后的dataElement的VR是显示还是隐式。说来说去0002,标准的第六章有说明::,面向对象的破概念非常烦的。第三步:读取普通tag直到搜寻到7fe0,0010这个最巨体的存储图像数据的dataElement它一个顶别人几十个上百个。我们在前一步已经把VR是显示还是隐式确定通过前面的图,也就是字节码处理而已无任何压力。显示情况下根据VR和Len?确定数据类型?跟数据长度直接读取就可以了。隐式情况下这破玩艺儿有点烦,只能根据tag字典确定它是什么VR再才能读取。标准的第六章。上面倒数第二段代码已经把重要的字典都列了出来。第四步:读取灰度像素数据并调窗以GDI的方式显示出来。这种号称医学什么影像的专家制定出来的标准读取像素数据应该有难度吧结果没想到这么的傻瓜。直接按像素从左到右从上到下一行行依次扫描。格式存储的是16位的灰度图像,其实有效数据只有12位,除去0所以最高值是2047。比方CT值从-1000到+1000,空气的密度为-1000水的密度为0金属的密度为+1000总共的值为2000调窗技术:即把12级灰度的数据通过调节窗宽窗位并让他在RGB模式下显示出来。还技术呢说实话这个也是没什么技术含量的所谓的技术,两句代码给你整明白。调节窗宽窗位到底什么意思,12位的数据那么它总共有2047个等级的灰度没有显示设备可以表达两千多级的明暗度就算有我们肉眼也无法分辨更无法诊断。我们要诊断是要提取关键密度值的数据在医院放射科呆久了你一定经常听医生讲什么骨窗肺窗之类的词儿,这就是指的这个“窗〞。比方有病人骨折了打了钢板我们想看金属局部来诊断那么我们应该抓取CT值从800到1000密度的像素也就是灰度值然后把它放到RGB模式下显示,低于800的不管值大小都显示黑色高于1000的不管值大小都显示白色。通过以上例子那么这个范围1000-800=200这个200表示窗宽,800+〔200/2〕这个表示窗位一句话,从2047个等级的灰度里选取一个范围放到0~255的灰度环境里显示。怎样把12位灰度影射到8位灰度显示出来呢,还怎么显示上面方法都给说明了根本上算半成品了。联想到角度制弧度制,设要求的8位灰度值为x的12位灰度值为y那么:x/255=y/2047那么x=255y/2047原理不多讲等比中项十字相乘法这个是初中的知识哈。初中没读过的童鞋飘过。。。原理过程讲完了代码走起Handler2{3stringfileName="";4Dictionary<string,string>tags=newDictionary<string,string>();//文件中的标签File;//文件流67//文件元信息////;////;/////;8publicBitmapgdiImg;//转换后的gdi图像9UInt32fileHeadLen;//文件头长度10longfileHeadOffset;//文件数据开始位置11UInt32pixDatalen;//像素数据长度12longpixDataOffset=0;//像素数据开始位置13boolisLitteEndian=true;//是否小字节序〔小端在前、大端在前〕14boolisExplicitVR=true;//有无VR1516//像素信息17intcolors;//颜色数RGB为3黑白为118publicintwindowWith=2048,windowCenter=2048/2;//窗宽窗位19introws,cols;20publicvoidreadAndShow(TextBoxtextBox1)21{22if(fileName==)23return;File=newBinaryReader((fileName));2526//(128,);2829if(newstring((4))!="DICM")30{("标识头,文件格式错误");32return;33}343536tagRead();3738IDictionaryEnumeratorenor=();39while(())40{41if(().Length>9)42{+=()+"\r\n";+=().Replace('\0','');45}+=()+().Replace('\0','')+"\r\n";48}();50}Handler(string_filename)52{53fileName=_filename;54}5556publicvoidsaveAs(stringfilename)57{58switch((('.')))59{60case".jpg":(filename,);62break;63case".bmp":(filename,);65break;66case".png":(filename,);68break;69default:70break;71}72}