【转】DICOM医学图像处理:开源库mDCM与DCMTK的比較分析(一),JPEG无损压缩DCM图像

转自:https://www.cnblogs.com/mfrbuaa/p/4004114.html 有修订

背景介绍:

近期项目需求,需要使用C#进行最新的UI和相关DICOM3.0医学图像模块的开发。在C++语言下,我使用的是应用最广泛的DCMTK开源库,在本专栏的起初阶段的大多数博文都是对DCMTK开源库的介绍和学习。眼下因为项目需要,现开始对mDCM开源库继续学习分析,因此本专栏接下来的文章大多以mDCM开源库为例进行医学图像的解说,DCMTK因为是C++语言开发的,所以作为我学习和剖析mDCM开源库的原始根据,我们并未放弃对DCMTK开源库的学习,而是通过更加细致的研读和分析DCMTK的C++源代码,从而更好更迅速的切换到C#语言环境下的医学图像处理。

DCMTK、mDCM(fo-dicom)的关系:

DCMTK的官网上有具体的说明文档,对该开源库的各个类,以及类之间的依赖关系进行了清晰的阐述。是学习DICOM3.0医学最新标准不可或缺的资源。其官网网址是:http://www.dcmtk.org/,活跃的开发人员论坛地址是:http://forum.dcmtk.org/index.php。

mDCM眼下了解是从DCMTK开源库转过来的,或者说是该开源项目的另一个分支,是用C#语言对C++版本号的医学图像开源库的再次组织和封装,其项目托管在GitHub上的官方网址是:https://github.com/rcd/mdcm。此处就需要提到fo-dicom了,该开源库是mDCM的升级版本号,里面添加了几大特性,详情可參见GitHub网址:https://github.com/rcd/fo-dicom。

大致上这三者的关系就是如此,更说明了我们依旧要以DCMTK开源库为根据,来高速学习和剖析mDCM(fo-dicom)开源库,要非常好的借助于DCMTK开源库丰富而具体的说明文档,以及活跃的开发人员论坛。以下我们就通过对DCM图像进行无损压缩这一任务来对照学习一下mDCM与DCMTK开源库的不同。

DCMTK与mDCM对DCM图像进行JPEG无损压缩的对照学习:

DCMTK的说明文档中对于dcmjpeg包的介绍中,就直接给出了一个利用JPEG无损压缩的实例。详细代码例如以下:

 

/*****************************************************************************
dcmjpeg程序包 
dcmjpeg提供了一个压缩/解压缩库以及可用工具。该模块包括一些类,可将DICOM图像对象在非压缩和JPEG压缩表示(传输协议)之间转换。无失真和有失真JPEG处理都被支持。这个模块实现了一族codec(编码解码器,由DcmCodec类派生而来),能够将这些codec在codec list中注冊,codec list是由dcmdata模块保存的。
主要接口类: 
--DJEncoderRegistration: 一个singleton(孤立)类,为全部支持的JPEG处理注冊编码器。在djencode.h中定义。 
--DJDecoderRegistration: 一个singleton(孤立)类,为全部支持的JPEG处理注冊解码器。在djdecode.h中定义。 
--DJCodecEncoder: JPEG编码器的一个抽象codec类。This abstract class contains most of the application logic needed for a dcmdata codec object that implements a JPEG encoder using the DJEncoder interface to the underlying JPEG implementation. This class only supports compression, it neither implements decoding nor transcoding. 在djcodece.h中定义。 
--DJCodecDecoder: JPEG解码器的一个抽象codec类。This abstract class contains most of the application logic needed for a dcmdata codec object that implements a JPEG decoder using the DJDecoder interface to the underlying JPEG implementation. This class only supports decompression, it neither implements encoding nor transcoding. 
工具: 
dcmcjpeg: Encode DICOM file to JPEG transfer syntax 
dcmdjpeg: Decode JPEG-compressed DICOM file 
dcmj2pnm: Convert DICOM images to PGM, PPM, BMP, TIFF or JPEG 
dcmmkdir: Create a DICOMDIR file 
举例: 
--用无失真JPEG压缩一幅DICOM图像文件。 
*****************************************************************************/ 
DJEncoderRegistration::registerCodecs(); // register JPEG codecs 
DcmFileFormat fileformat; 
if (fileformat.loadFile("test.dcm").good()) 
{ 
DcmDataset *dataset = fileformat.getDataset(); 
DcmItem *metaInfo = fileformat.getMetaInfo(); 
DJ_RPLossless params; // codec parameters, we use the defaults 
// this causes the lossless JPEG version of the dataset to be created 
dataset->chooseRepresentation(EXS_JPEGProcess14SV1TransferSyntax, ¶ms); 
// check if everything went well 
if (dataset->canWriteXfer(EXS_JPEGProcess14SV1TransferSyntax)) 
{ // force the meta-header UIDs to be re-generated when storing the file // since the UIDs in the data set may have changed delete metaInfo->remove(DCM_MediaStorageSOPClassUID); delete metaInfo->remove(DCM_MediaStorageSOPInstanceUID); // store in lossless JPEG format fileformat.saveFile("test_jpeg.dcm", EXS_JPEGProcess14SV1TransferSyntax); 
} 
}   
DJEncoderRegistration::cleanup(); // deregister JPEG codecs

 

 

(详细的project配置如前一篇博文所述http://blog.csdn.net/zssureqh/article/details/38460445,在此就不在反复介绍了)

通过这段代码能够顺利实现对DCM图像的JPEG无损压缩。例如以下图所看到的,

image

利用Sante DICOM Editor专业DCM图像浏览编辑器打开压缩前后的图像,发现图像质量没有区别,压缩前实际大小为4572K,压缩后为1774K,压缩效果良好。

   设想:既然mDCM开源库就是对DCMTK开源库的封装,那么两个开源库中应该会有相应的功能,同样或类似的函数。由DCMTK实例中的代码可知,演示样例中仅仅调用了DcmFileFormat的loadFile、saveFile和DcmDataset的chooseRepresentation和canWriteXfer四个函数,并且从函数名称上看,就知道实际达到压缩效果的应该是DcmDataset的chooseRepresentation和canWriteXfer的两个函数,那么接下来我们看看mDCM开源库下的DcmDataset是否有相相应的函数呢?

通过VS2012的对象浏览器能够看到,mDCM开源库下的Dicom.Data命名空间中DcmDataset类中的确拥有一个类似的函数ChangeTransferSyntax,例如以下图:

image

   推測:直接调用mDCM的Load、ChangeTransferSyntax和Save三个函数,应该能够实现与DCMTK同样的效果,即完毕对DCM的JPEG无损压缩。

详细代码例如以下,

 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Dicom; 
using Dicom.Data; 
using Dicom.Codec; 
using Dicom.Codec.JpegLs; 
namespace JpegLossLess 
{ class Program { static void Main(string[] args) { DicomCodec.RegisterCodecs(); //Dicom.Codec.JpegLs.DcmJpegLsCodec.Register(); string fName = string.Format("d:\\dcm\\test.dcm"); DicomFileFormat ff = new DicomFileFormat(); ff.Load(fName, DicomReadOptions.Default | DicomReadOptions.DeferLoadingPixelData);//ff.Load(fName, DicomReadOptions.None); DcmPixelData pixels = new DcmPixelData(ff.Dataset);DcmJpegLsParameters JpegParameters = new DcmJpegLsParameters(); ff.FileMetaInfo.TransferSyntax = DicomTransferSyntax.JPEGProcess14SV1;ff.Dataset.ChangeTransferSyntax(DicomTransferSyntax.JPEGProcess14SV1, JpegParameters);string OutFile = string.Format(@"d:\dcm\outfile.dcm"); ff.Save(OutFile, DicomWriteOptions.Default);  } } 
}


 

 

project顺利编译成功,执行调试后,也相同出现了大小为1774K的文件,可是利用Sante DICOM Editor打开该文件时,出现错误,例如以下图所看到的:

image

利用DCMTK开源库的工具包dcmdump.exe查看利用mDCM压缩后的文件outfile.dcm,输出例如以下错误提示:

image

警告(Warning)提示(0008,0000)数据元素的数值有误,错误(Error)是出现了无法识别的标签和数据(f752,0e57),经过查看DICOM3.0标准,并未发现有(f752,0e57)该标签,利用UltraEdit打开DCMTK压缩后的文件test_jpeg.dcm和mDCM压缩的文件outfile.dcm,通过查找功能发现,(f752,0e57)字段实际上是标准的JPEG无损压缩后的(7fe0,0010)字段的Value Field内容(例如以下图所看到的),因此推測应该是mDCM压缩后的文件头中某个字段写入有误,导致在读取数据体的时候并未依照原本的DICOM3.0标准去读取。

解决方法:

利用DCMTK的project来读取我们利用mDCM压缩后的文件outfile.dcm,结果单步调试进入后,利用Load函数读取Jpeg压缩后的图像时,metainfo部分是没有问题的。可是当读取到dataset时,对于(0008,0000)元素的读取有误,正确的(0008,0000)元素的解析方式为

clip_image002

元素标签,即(group,element)为:08 00 00 00——(0008,0000)

元素类型,即VR为:55 4C——UL

元素长度,即VL为:04 00——0004(长度为4)

元素值域,即Value Field:B8 00 00 00——00000008(值为184)

可是在读取dataset时,将55 4c 04 00所有当成了长度来读取,因此推測是将原本为ExplicitUL格式的元素当做了ImplicitVR格式来读取了,文件流的指针_streamPosition直接从0x0000000000000160直接跳转到了0x0000000000044db5,例如以下图所看到的:

clip_image004

因此尝试在mDCM的c#project中加入手动改动文件元信息中传输语义的语句,

 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Dicom; 
using Dicom.Data; 
using Dicom.Codec; 
using Dicom.Codec.JpegLs; 
namespace JpegLossLess 
{ class Program { static void Main(string[] args) { /**************************************************** * 对照C++中DCMTK对于DICOM进行JPEG无损压缩,来学习C# * 中Dicom库的使用 * 2014-08-06 * zssure ****************************************************/ DicomCodec.RegisterCodecs(); string fName = string.Format(@"d:\dcm\test.dcm"); DicomFileFormat ff = new DicomFileFormat(); ff.Load(fName, DicomReadOptions.Default | DicomReadOptions.DeferLoadingPixelData);DcmJpegLsParameters JpegParameters = new DcmJpegLsParameters();ff.FileMetaInfo.TransferSyntax = DicomTransferSyntax.JPEGProcess14SV1;ff.Dataset.ChangeTransferSyntax(DicomTransferSyntax.JPEGProcess14SV1, JpegParameters);string OutFile = string.Format(@"d:\dcm\outfileJpeg22.dcm"); ff.Save(OutFile, DicomWriteOptions.Default); } } 
}

project编译后,可以顺利完成压缩DCM的功能,至此利用mDCM对DICOM图像进行JPEG无损压缩的目的已经实现。

总结:

DICOM3.0标准的第10部分中,有对于dcm文件存储格式的具体介绍,当中对于传输语义的介绍例如以下:

1)Except for the 128 byte preamble and the 4 byte prefix, the File Meta Information shall be encoded using theExplicit VR Little Endian Transfer Syntax (UID=1.2.840.10008.1.2.1) as defined in DICOM PS 3.5. Values of each File Meta Element shall be padded when necessary to achieve an even length, as specified in PS 3.5 by their corresponding Value Representation. The Unknown (UN) Value Representation shall not be used in the File Meta Information. For compatibility with future versions of this Standard, any Tag (0002,xxxx) not defined in Table 7.1-1 shall be ignored. Values of all Tags (0002,xxxx) are reserved for use bythis Standard and later versions of DICOM. Data Elements with a group of 0002 shall not be used in datasets other than within the File Meta Information

2)The Transfer Syntax used to encode the DataSet cannot be changed within the Data Set; i.e., the Transfer Syntax UID Data Element may not occur anywhere within the Data Set, e.g., nested within a Sequence Item.

因此DCM文件元信息中的标签(0002,0010),即传输语义,对于DCM文件的数据体Dataset的读取起到关键的作用。通过此次的mDCM开源库与DCMTK开源库的比較发现,两者尽管大多的函数都同样,且名称和功能都类似,可是对于细节部分应该注意。

如今对两个开源库对DCM文件的JPEG无损压缩功能所须要调用的函数进行一个对照分析,以找到两者之间的区别所在,详细分析例如以下表

mDCM

DCMTK

1) DicomFileFormat.Load,打开文件(也是通过文件流的方式一一读取DCM文件的各个信息到内存中)

2) DicomFileFormat.Dataset.ChangeTransferSyntax,该函数与DCMTK中的chooseRepresentation函数类似,在參数中都须要指出新的传输语义,函数内部会依据新的传输语义来改动数据体的存储方式。该函数主要完毕的功能是:

比較新旧传输语义、依据新旧语义决定数据体是否解压缩或压缩(Dicom.Codec.Encode或者Dicom.Codec.Decode)。

3) DicomFileFormat.Save,存储文件,可是该函数中并不须要填写新的传输语义

【注】:这一点与DCMTK中的saveFile函数不同。这也就是上个周C#版本号的mDCM实现对DCM数据的JPEG无损压缩后无法顺利读取的原因。由于数据体存储格式不是依照文件元信息中指定的传输语义存储的,或者说文件元信息中的传输语义没有改动为JPEG无损压缩的方式。

1) DicomFileFormat::loadFile,导入文件,主要是DcmMetaInfo和DcmDataset两部分;

2) Dataset::chooseReresentation,參数中会出现新旧传输语义TransferSyntax,函数依据新的语义对对应数据(主要是像素数据)进行处理,会调用DcmPixelData::canChooseRepresentation、DcmPixelData::chooseRepresentation

3) Dataset::canWriteXfer,參数中是新改动后的传输语义。

4) DcmFileFormat::saveFile,參数中须要指出改动后的传输语义。

——》随后会调用dcfilefo.cc文件里的validateMetaInfo函数(该函数中也须要指定新的传输语义)。

——》对文件元信息的各个元素分别调用DcmMetaInfo::search和chekMetaHeaderValue两个函数(在该函数内,会检測各个元信息元素是否存在,不存在会新建之并插入,其參数中就须要指出新的传输语义)

——》DcmElement::putString将新的传输协议写入到MetaInfo中。(基本调用流程例如以下图。

clip_image002[5]

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

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

相关文章

xfire客户端对返回list很挑剔,所以需要使用泛型。

casldap异常分析 | xfirewebservice(服务器配置篇) 2008-12-31xfirewebservice(客户端调用篇) 服务接口,就是用来调用的,所以客户端显得尤为重要,xfire客户端对返回list很挑剔,所以需要使用泛型。 如何建立webservice client 步骤…

在虚拟机上运行vxWorks

Vxworks是一个嵌入式系统,主要运行在arm、ppc、mips等嵌入式处理器上,它同样可以运行在X86处理器上。风河公司开发的tornado开发环境就 包括了pentium版本,并且发布了相应的bsp。因此我们可在vmware虚拟机上运行vxworks,利用虚拟机…

使用SDL打造游戏世界之入门篇 - 7

打开和显示图片在这个例子里我们将学习如何使用SDL程序中打开和显示图片。示例程序将绘制一个漂亮的背景,上面显示一个正方形图案,并可以使用键盘的方向键移动它。如果比较熟悉“推箱子”这个游戏,可以看出这个程序实际就是推箱子游戏的基础。…

【转】GPS从入门到放弃(一) --- GPS基础原理

转自:https://blog.csdn.net/tyst08/article/details/100529424 GPS从入门到放弃(一) — GPS基础原理 GPS,全称Global Positioning System,已经广泛应用于我们的日常生活中了,现在的智能手机 里都会自带G…

【转】10个推荐的 PACS/DICOM Server开源项目

10个推荐的 PACS/DICOM Server开源项目 转自:https://zhuanlan.zhihu.com/p/65437040 soolaugust 喜欢我的分享可以关注公众号:雨夜随笔 35 人赞同了该文章 本文仅授权给公众号:雨夜随笔, 欢迎关注 本文翻译自:To…

字节序、位序

字节序 字节序,又称端序、尾序,英文单词为Endian,该单词来源于于乔纳森斯威夫特的小说《格列佛游记》,小说中的小人国因为吃鸡蛋的问题而内战,战争开始是由于以下的原因:我们大家都认为,吃鸡蛋前…

怎么抓取屏幕截图计算机考试时间,定时抓屏快照(电脑截屏工具)V4.8 最新版

定时抓屏快照(电脑截屏工具)是一款非常实用的电脑屏幕定时抓拍软件。想定时截取电脑屏幕?定时抓屏快照(电脑截屏工具)轻松帮助用户。马上要放假了,家长一定很担心小孩最新的上网情况,看是在电脑上玩什么,用户通过该软件可以及时了…

【转】matlab函数编译成dll供Cpp调用的方法

转自:https://www.cnblogs.com/vincenzo/archive/2009/09/09/1563467.html 以前做过matlab7与c的混合编程:将m函数编译成dll给C调用,从而加快开发的进度。但是今天在matlab2008b下面又做了一遍,发现matlab又改了很多东西&#xf…

可以测试流放之路伤害的软件,测试平台及细节一览 - 《流放之路》国服硬件需求测试:低配也能续写ARPG传奇 - 超能网...

测试平台、场景说明测试平台测试平台配置主要分为两套,第一套配置为Skylake平台基础搭建的ASUS MAXIMUS VIIIGEN(Z170)主板,处理器为Intel Core i7-6700K,内存是G.Skill Ripjaws V 4GB DDR43200x2组成的双通道;第二套配置为Kaveri…

关于增强(五)-Class Enhancement

Class/Interface增强允许增加, 对已有的方法增加可选参数 添加方法,事件,事件处理 参考接口 对存在的方法添加出口,其中包括方法开始前的出口(Pre-Exit),方法结束快结束的出口(Post-Exit)&#…

【转】彻底理解cookie,session,token

转自:https://zhuanlan.zhihu.com/p/63061864 彻底理解cookie,session,token 发展史 1、很久很久以前,Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, 不需要记录谁在某一段时间里都浏…

【转】c#数字图像处理(一)Bitmap类、 Bitmapdata类和 Graphics类

转自:https://www.cnblogs.com/dearzhoubi/p/8553763.html Bitmap类、 Bitmapdata类和 Graphics类是C#图像处理中最重要的3个类,如果要用C# 进行图像处理,就一定要掌握它们。 1.1 Bitmap类 Bitmap对象封装了GDI中的一个位图,此位图由图形图像及其属性的像素数据组成…

【转】c#数字图像处理(二)彩色图像灰度化,灰度图像二值化

转自:https://www.cnblogs.com/dearzhoubi/p/8571652.html 为加快处理速度,在图像处理算法中,往往需要把彩色图像转换为灰度图像,在灰度图像上得到验证的算法,很容易移 植到彩色图像上。 24位彩色图像每个像素用3个字节表示,每个字节对应着R、G、B分量的亮度(红、绿…

【转】c#数字图像处理(三)灰度直方图

转自:https://www.cnblogs.com/dearzhoubi/p/8621804.html 灰度直方图是灰度的函数,描述的是图像中具有该灰度级的像素的个数。如果用直角坐标系来表示,则它的横坐标是灰度级,纵坐标是该灰度出现的概率(像素的个数)。 using System; using System.Collections.Gener…

电梯门禁系统服务器一般在哪,别被吓住了,电梯门禁(梯控)安装其实并不难...

电梯门禁又称梯控,主要用于对电梯的出入权限进入控制,只有授权卡在读卡器刷过后,才能到达指定楼层。梯控的使用越来越普遍了,很多人觉得梯控很神秘,很高不可攀,其实说到底它不过是门禁的一种,只…

【转】c#数字图像处理(四)线性点运算

转自:https://www.cnblogs.com/dearzhoubi/p/8622325.html 灰度图像的点运算可分为线性点运算和非线性点运算两种。 4.1线性点运算定义 线性点运算就是输出灰度级与输入灰度级呈线性关系的点运算。在这种情况下,灰度变换函数的形式为: g(x, y)pf(x,y)L 其中 f(x,…

工作人员做好项目协调服务器,项目团队协作做好三件事

原标题: 项目团队协作做好三件事大家也许在小时候就听过三个和尚的故事:当庙里有一个和尚时,他一切自己做主,做得很自在;当庙里有两个和尚时,他们通过协商可以自觉地进行分工合作,同样做的不错;可当庙里来了…

给vc6插上翅膀

最重要的当然是VC助手了。。我比较喜欢低版本的Visual.Assist.v6.0.0.1079.zip,环保类型的 但无奈我的vs2005也想使用这个插件,所以我选择了VisualAssistXv10,目前装的是Visual.Assist.X.10.4.1626.0 以前还用过一些版本很奇怪的,…

【转】[程序集清单定义与程序集引用不匹配]分析及解决

转自:https://www.cnblogs.com/shuangzimuchangzhu/p/8572817.html 什么是程序集清单(Assembly Manifest)? 我们知道,在.net中。程序是以程序集为单位进行打包的,通常一个.exe文件或一个.dll文件就是一个程序集。程序集一般包含了以下几个部…

dos如何修改远程服务器的密码,dos命令登入远程服务器

dos命令登入远程服务器 内容精选换一换远程桌面链接Windows云服务器报错:连接被拒绝,因为没有授权此用户账户进行远程登录。Windows远程桌面相关权限配置异常。在运行窗口输入secpol.msc,打开组策略编辑器打开"本地策略 > 用户权限分…