精华内容
下载资源
问答
  • 简述了医学图像无损压缩的基本步骤,差分脉冲编码调制(DPCM)在无损压缩中的作用进行了分析和实现,并在此基础上,提出将整数小波变换与DPCM相结合的医学图像无损压缩方法。通过对比和分析实验结果可知,采用该...
  • 针对医学图像数据量大、存储和传输内存和...磁共振(MR)图像和计算机断层(CT)图像两种医学图像进行实验,实验结果表明,与其他方法相比,所提方法具有明显的优势,在高压缩比的情况下能够保留良好的图像质量。
  • 随着社会的发展和医疗技术的进步,人们身体健康的关心程度越来越高。医学影像已经不再是仅供...由于第二代小波采用提升方法能够实现整数变换,因而能够实现图像的无损压缩,显然,它是一种很适于医学图像压缩方法。
  • 为解决海量医学数据与有限存储空间和传输带宽之间的矛盾,提出一种适用于PACS(picture archiving and communication system)系统的医学图像近无损压缩算法。首先病变区域和背景区域分别进行剪切波变换和小波变换;...
  • 算法,提出了自己的改进意见:首先对医学图像进行嵌入零树编码,然后对编 码后的符号串进行行程编码,最后再对行程编码后的码流进行自适应二进制算 术编码。实验结果表明,这种零树与行程相结合的医学图像编码方案...
  • 给定的医学图像采用基于“提升”算法的整型小波变换,变换后的小波域图像编码。编码时,针对医学DICOM标准的数据结构,在...实验证明,该方法视觉效果良好,实现了医学图像的无损压缩,有较好的压缩比和压缩效果。
  • jpeg压缩的matlab代码MedImageProcMath 注意:DICOM数据的Mathematica处理在版本12.1中已更改。...使用Mathematica存储库进行医学图像处理是用于Mathematica代码,将轴向CT身体图像分为身体像素和非身体像素。 该分
  • 为了满足无线医疗应用对于图像传输的需求,提出一种有效的医学图像分割... 根据预定义的优先级顺序,分别ROI和非感兴趣区域(region of not interest,RONI)进行 JPEG2000 近无损压缩和有损压缩,并依次进行传输? 重构后图
  • 为进一步提高医学图像压缩效率,减少网络存储和带宽的要求,提出了一种基于几何流多级树Bandelet分割编码的医学图像压缩方法。首先,结合图像结构的几何规律,利用稀疏表示方法构建图像的灰度级有规则变化的方向...
  • 背景介绍: 最近项目需求,需要使用C#进行最新的UI和相关...目前由于项目需要,现开始mDCM开源库继续学习分析,因此本专栏接下来的文章会大多以mDCM开源库为例进行医学图像的讲解,DCMTK作为我学习和剖析mDC的依据。

    背景介绍:

    最近项目需求,需要使用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/ignacioinnovo/mdcm。此处就需要提到fo-dicom了,该开源库是mDCM的升级版本,里面增加了几大特性,详情可参见GitHub网址:https://github.com/fo-dicom/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, params); 
    // 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

    (具体的工程配置如前一篇博文所述http://blog.csdn.net/zssureqh/article/details/38460445,在此就不在重复介绍了)

    通过这段代码可以顺利实现对DCM图像的JPEG无损压缩。如下图所示,


    利用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(); 
                string fName = string.Format("d:\\dcm\\test.dcm"); 
                DicomFileFormat ff = new DicomFileFormat(); 
                ff.Load(fName, DicomReadOptions.Default | DicomReadOptions.DeferLoadingPixelData);
                DcmJpegLsParameters JpegParameters = new DcmJpegLsParameters(); 
                ff.Dataset.ChangeTransferSyntax(DicomTransferSyntax.JPEGProcess14SV1, JpegParameters);
                string OutFile = string.Format(@"d:\dcm\outfile.dcm"); 
                ff.Save(OutFile, DicomWriteOptions.Default);  
            } 
        } 
    }


    工程顺利编译成功,运行调试后,也同样出现了大小为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的工程来读取我们利用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#工程中添加手动修改文件元信息中传输语义的语句,

    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); 
            } 
        } 
    }


    工程编译后,能够顺利完成压缩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]

     

    作者:zssure@163.com

    时间:2014-08-11

    展开全文
  • 上周通过单步调试,找出了开源库mDCM与DCMTK在DICOM图像进行JPEG无损压缩时的细小区别,并顺利实现了在C++和C#环境下DICOM图像的压缩。但是问题接踵而至啊,随着项目的深入,发现在单独的测试工程中可以实现的...

    背景:

            上周通过单步调试,找出了开源库mDCM与DCMTK在对DICOM图像进行JPEG无损压缩时的细小区别,并顺利实现了在C++和C#环境下对DICOM图像的压缩。但是问题接踵而至啊,随着项目的深入,发现在单独的测试工程中可以实现的mDCM版本,在嵌入到项目整体中后,却意外地出现了错误,并未顺利实现DICOM图像的JPEG无损压缩。因此需要继续详细对比分析mDCM与DCMTK两者,期望寻找原因。

    问题分析:

            开启项目的日志功能后,得到的信息反馈为:

    No registered codec for transfer syntax! 在 Dicom.Data.DcmDataset.ChangeTransferSyntax(DicomTransferSyntax newTransferSyntax, DcmCodecParameters parameters),在…………………………处。

            从日志得到的反馈来看,应该是JPEG的编码器注册失败。而编码器部分包含在mDCM开源库的Dicom.Codec64.dll程序集中。因此单步调试进入,查看工程是否顺利加载了Dicom.Codec64.dll模块

            首先单步进入的是上周测试用的独立工程JpegLossLess,通过在Program.cs中调用Dicom.Codec.DicomCodec.RegisterCodecs();使得程序进入到DicomCodec.cs文件,程序运行到静态类DicomCodec的静态方法RegisterCodecs内。

    clip_image002

            如上图所示,方法RegisterCodecs内部通过C#的程序集的动态加载和反射技术,顺利识别了工程引用中添加的Dicom.dl程序集Dicom.Codec64.dll程序集

    接下来单步调试到整体工程中,程序从主框架转移到我们手动添加的调用Dicom.Codec.DicomCodec.RegisterCodecs();函数处,如下图所示:

    image

             经过几次的调试发现,使用RegisterCodecs函数并未顺利的注册JPEG编码器,识别出的17个程序集中只有Dicom.dll模块。通过浏览DicomCodec.cs文件源码发现,RegisterCodecs函数是静态类DicomCodec的静态函数,该函数实现的是自动注册JPEG所有编码器。继续浏览发现,静态类DicomCodec还有类似的其它函数,如public static void RegisterCodec(DicomTransferSyntax ts, Type type);public static void RegisterExternalCodecs(string path, string pattern);两个函数,分别是注册指定传输语义的解码器和注册指定路径下的程序集中的解码器。由于我们利用RegisterCodecs函数并未实现自动加载JPEG解码器的功能,而且工程中已经添加引用了DicomCodec64.dll程序集,并且在调试时刻VS2012的模块窗口已经显示顺利加载了DicomCodec64.dll程序集。所以此时决定尝试手动加载DicomCodec64.dll程序集,即用下面的代码替换原本的Dicom.Codec.DicomCodec.RegisterCodecs();语句,

           string path = System.IO.Directory.GetCurrentDirectory();
           string pattern = "Dicom.Codec64.dll";
           DicomCodec.RegisterExternalCodecs(path, pattern);

            此刻单步调试可以看到,已经成功的实现了DicomCodec64.dll程序集中JPEG解码器的注册,完成了将DICOM图像JPEG压缩的功能与整体工程的整合。

    学习总结:

    1)GetReferencedAssemblies函数能否返回工程中的所有引用程序集?

            通过对比上述的自动手动的注册代码,发现两者的最终都是利用的GetExportedTypes函数来完成注册,具体代码都是Type[] types = asm.GetExportedTypes();来提取相应的解码器,唯一不同的是自动注册中是利用AssemblyName[] referenced = main.GetReferencedAssemblies();提取该模块的引用程序集,而手动注册是利用的Assembly.LoadFile函数加载手动指定的程序集文件,难道是GetReferencedAssemblies函数出现了问题?GetReferencedAssemblies函数到底能不能返回我们工程中所有的引用程序集呢?

            在MSDN搜索一下GetReferencedAssemblies函数的功能,描述为:Gets the AssemblyName objects for all the assemblies referenced by this assembly.

    乍一看,好像该函数是可以返回我们工程中所有加载的程序集的名称。但是仔细分析一下,描述中提到的是"this assembly”,此处this 应该指的是调用RetReferencedAssemblies函数的程序集,因此该函数应该获得的是当前模块所引用的所有程序集,而并不是我们起初认为的整个工程的引用程序集。经过漫长的搜索,终于在一篇stackoverflow的博文(http://stackoverflow.com/questions/3971793/what-when-assembly-getreferencedassemblies-returns-exe-dependency)中找到了对“提取工程所有依赖程序集”的相关说明,文中作者不仅给出了实现的方法,而且给出了为什么GetReferencedAssemblies函数没有返回工程所有引用程序集的原因(http://msdn.microsoft.com/en-us/magazine/cc163641.aspx)。此处简单的对其归纳一下,并借用一下原作者的图:

            如下图所示,假设我们在模块A中调用了GetReferencedAssemblies函数,那么按照MSDN中对应的解释,函数应该返回this——即A所引用(更确切的说是直接应用)的程序集B、C、D。然而如下图左所示,程序集C和D又分别引用了其他的程序集,所以此处我们并未直接获取到整个工程中所有的程序集。因此自动加载的时候并未顺利的返回我们需要的Dicom.Codec64程序集。

            说到这里,我想提取工程所有引用程序集的方法已经呼之欲出了,最简单的就是我们可以对GetReferencedAssemblies的首次返回值进行递归调用,那么自然而然就可以得到所有的引用程序集A-J。但是博文中作者是按照上图右中的方式来提取所有引用程序集的,因为递归会影响程序的性能,尤其是程序模块众多的时候。简言之,就是利用算法导论中的“前序遍历”来提取所有的引用程序集,具体代码可以从给出的参考博文下载。

    2)C#的静态类与Singleton设计模式

            在对比mDCM与DCMTK两个开源库对于JPEG解码器注册的源代码后,发现在用C++完成的DCMTK开源库中,使用的是Singleton设计模式的DcmCodecList类来完成JPEG各种解码器注册的,而用C#编写的mDCM开源库使用的是C#的静态类public static DicomCodec。这两种方式可以实现相同的功能,由于刚开始从C++转向C#,对于这两者的区别不是很清楚,因此搜索了一下,仅摘取部分重要片段贴在博文中,便于以后查阅。

    【摘要1】:http://bbs.csdn.net/topics/370008452

    除了跨程序集的边界问题,static 类和模仿 GoF C++ 版的单件没有本质的区别。我感兴趣的讨论在于这两者在满足同样的动机的情况下,是否达成了同样的效果,我个人的看法是,静态类有简单和优雅的一面。事实上,在Java和C#方面,GoF的设计模式本身有问题,这就是经典的Double Lock Check问题(看 CLR via C#)。

    粗略地说,在C# 4中,这些模式消失了:单件(静态类)、策略(委托和Lambda)、观察者(事件)、装饰(扩展方法)、工厂(部分靠反射实现)、代理(表达式树和动态类)、迭代器(yield return语法),等等,如果你按照GoF的实现来做这些,你反而舍近求远了。

    最后,不光是 singleton,我对设计模式一个普遍的看法是,随着编程语言的进步,所有设计模式的实现都将消亡,而思想保存了下来。设计模式的本质也可以说是为了修饰语言的缺陷,一种优雅的语言,不需要设计模式(这个观点是我一个大学同学提出的,他也是一位 Ruby 社区的专家)。

    【摘要2】:http://www.cnblogs.com/utopia/archive/2010/03/02/1676390.html

    静态类的语义是全局唯一代码段,而单件的语义是全局唯一对象实例;

    语义上是完全不同地,不能说起修饰都是“全局唯一”就放一块比较;

    如果是这样那么所有public修饰的东西我们不是都得比较一翻了;

    另外:如果要研究对象设计,那么请先抛开代码。对象设计是本身哲学性和世界观的表达。

    如何把现实的东西用概念还原表达出来,才是对象设计的实质。而代码则是体现你头脑里那个概念模型的工具。

    【摘要3】:http://blog.csdn.net/lyrebing/article/details/1902235

    单例模式的目的是为了在程序中提供类的唯一实例,而且仅提供唯一的访问点。静态不需要实例,仅提供一个全局功能。使用单例可以继承,实现接口,而静态类不能。静态方法不能访问类中的实例字段,因为静态方法不是通过实例来访问的。而单例中的方法却可以访问那个唯一实例中的实例字段。静态方法在执行后,会释放掉它所创建的所有对象。而单例中的方法却可以保留。静态字段仅是提供全局的功能,大家共享同一内存位置。访问单例中的字段是类的唯一实例中的字段,大家只能访问这个实例的字段。

     

    作者:zssure@163.com

    时间:2014-08-17

    展开全文
  • 背景介绍: 近期项目需求,需要使用...眼下因为项目需要,现开始mDCM开源库继续学习分析,因此本专栏接下来的文章大多以mDCM开源库为例进行医学图像的解说,DCMTK因为是C++语言开发的,所以作为我学习和剖析mDCM开.

    转自: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]

    展开全文
  • 背景介绍: 近期项目需求,须要使用...眼下因为项目须要,现開始mDCM开源库继续学习分析,因此本专栏接下来的文章会大多以mDCM开源库为例进行医学图像的解说,DCMTK因为是C++语言开发的,所以作为我学习和剖...

    背景介绍:

    近期项目需求,须要使用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]

     

    作者:zssure@163.com

    时间:2014-08-11

    展开全文
  • dicom格式图像是医学图像中最常见的影像格式,这种格式不利于我们进行处理和分析。因此,要将其转换成其他格式的图像储存,便于处理。 本实验要求: 读取DICOM图像 将其转换为BMP和JPEG格式 计算峰值信噪比 ...
  • 上周通过单步调试,找出了开源库mDCM与DCMTK在DICOM图像进行JPEG无损压缩时的细小差别,并顺利实现了在C++和C#环境下DICOM图像的压缩。可是问题接踵而至啊,随着项目的深入,发如今单独的測试project中能够实现...
  • 首先图像进行非下采样Contourlet分解,分别得到低频子带系数和高频子带系数,然后低频子带系数采用区域能量加权的融合规则,高频子带系数则选取区域标准差比例加权作为融合规则,最后进行非下采样Contourlet逆...
  • 通过研究二维图像小波变换的迭代特征,提出了一种适用于PACS系统的医学图像多分辨率编码算法,该算法优先频率较低的子带图像进行编码,再依次频率较高的子带图像进行编码;在传输和回放时先处理频率较低的子带...
  • mia - 医学图像分析这个 Matlab GUI 使您能够对医学图像进行分析。 提供了一组工具来执行基于切片或体积的分析。 另一方面,该程序可以被认为是有用的先前开发的和自己的用于医学图像处理的 matlab 工具的包装。 ...
  • 压缩压缩或比特率(每单位时间传送的比特数)减少涉及使用比原始表示更少的比特信息进行编码。 压缩可以是有损的或无损的。 无损压缩:无损数据压缩是一类数据压缩算法,可以从压缩数据中完美地重建原始数据。 ...
  • 利用整数小波变换和零树编码算法对医学图像进行压缩研究,在对嵌入零树小波编码(Embedded Zero-tree Wavelet,EZW)算法研究的基础上提出一种基于小波系数的嵌人零树小波编码算法。其主要包括:对小波图像的低频...
  • 具体做法是先使用较小的结构元获得形态学梯度图像,后续接一个小尺寸滤波器进行平滑,最后进行非线性灰度级压缩后叠加到原图上。示例结果见fig1~fig5。 fig1 原图 fig2 形态学梯度图像 fig3 滤波后...
  • 考虑到随机测量矩阵存在硬件上存在无法实现的缺陷,结合压缩感知的稀疏投影理论,提出了基于多项式确定性矩阵的尺度不变特征变换(SIFT)医学图像配准算法。通过增加方向梯度数提高特征向量的有效性,利用测量数为7...
  • 为解决海量医学数据与有限存储空间和传输宽度之间的矛盾,提出一种适用于PACS(图片存档和通信系统)系统的医学图像近无损压缩算法。首先尺寸区域和背景区域分别进行剪切波变换和小波变换;其次,拾取一些能够近似...
  • 首先对图像进行SCoW预处理分块,压缩预处理数据;然后修正细分割处理,提取各超像素块的均值特征;最后设计一种改进的FLICM算法各超像素块进行聚类,完成图像分割。与原FLICM算法相比,结合SCoW的改进FLICM算法的...
  • 本文提出了一种计算有效的算法,用于使用二级总变化量(HDTV2)正则化进行... 在医学图像上的实验表明,该方法在峰值信噪比(PSNR),结构相似性指标(SSIM)和收敛速度方面优于电视和HDTV2重建模型的几种快速算法。
  • 然后利用自适应梯度加权的融合规则得到融合的测量数据,并融合测量数据进行随机压缩采样;最后通过CoSaMP算法采样数据进行信息重构实现测量数据的恢复。该方法克服了图像融合时信息畸变的缺陷,并且可以根据不同...

空空如也

空空如也

1 2 3 4 5
收藏数 82
精华内容 32
关键字:

对医学图像进行压缩