? 使用DCMTK实现DICOM文件浏览器dicom explorer_澳门亚博资讯网 澳门亚博,澳门亚博,yabo88真人娱乐
首页 > 调查 > 正文

小萝莉的猴神大叔_使用DCMTK实现DICOM文件浏览器dicom explorer

之前一直使用别人的免费浏览工具来浏览DCM图像,或多或少都存在小的问题,要么完全免费但是功能不全不好用,要么就是收费需要定期下载版本申请试用,折腾来折腾去很是费心,决定最近自己写个简单的,不求功能强大只求自己用起来得心应手。

底层文件的读取使用DCMTK3.6.3的DCMData包;考虑支持跨平台,上层显示使用QT来做。

?在Linux和windows两个平台下编译DCMTK生成的Config文件夹中的头文件内容是不同的,为了更好地组织两个平台的头文件和库文件,在dcmtk文件夹分别新建linux和win文件夹,将ubuntu下编译后的include文件夹拷贝到linux下,将win7下编译后的include文件夹拷贝到win下。读取文件主要使用DCMTK的DcmData库,该库依赖了ofstd,oflog库,为了支持RLE压缩和JPEG压缩,还需要dcmjpeg库。以linux为例,将编译后的config文件夹下的include目录和源码中的ofstd,oflog,dcmjpeg,dcmdata文件夹中的include文件夹拷贝到dcmtk/linux/include目录下,并在工程文件.pro中将这些目录添加到INCLUDEPATH中;

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/
else:unix: INCLUDEPATH += $$PWD/dcmtk/linux/include/

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/config
else:unix: INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/config

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/ofstd
else:unix: INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/ofstd

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/ofstd/diag
else:unix: INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/ofstd/diag

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/ofstd/variadic
else:unix:  INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/ofstd/variadic

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/oflog
else:unix:  INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/oflog

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/oflog/config
else:unix: INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/oflog/config

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/oflog/helpers
else:unix: INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/oflog/helpers

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/oflog/internal
else:unix:  INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/oflog/internal

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/oflog/thread
else:unix:  INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/oflog/thread

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/oflog/spi
else:unix:  INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/oflog/spi

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/dcmjpeg
else:unix:  INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/dcmjpeg

win32: INCLUDEPATH += $$PWD/dcmtk/win/include/dcmtk/dcmdata
else:unix: INCLUDEPATH += $$PWD/dcmtk/linux/include/dcmtk/dcmdata

?

将这几个库文件也拷贝到dcmtk/linux/lib文件夹下,使用到的库文件和.pro代码如下:

DEPENDPATH += C:Program FilesMicrosoft SDKsWindowsv6.0ALibx64;

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -lcharset_d
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -lcharset_d
else:unix: LIBS += -lcharset

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -llibiconv_d
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -llibiconv_d
else:unix: LIBS += -liconv

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -lofstd
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -lofstd
else:unix: LIBS += -L$$PWD/dcmtk/linux/lib/ -lofstd

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -loflog
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -loflog
else:unix: LIBS += -L$$PWD/dcmtk/linux/lib/ -loflog

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -ldcmjpeg
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -ldcmjpeg
else:unix: LIBS += -L$$PWD/dcmtk/linux/lib/ -ldcmjpeg

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -ldcmimage
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -ldcmimage
else:unix: LIBS += -L$$PWD/dcmtk/linux/lib/ -ldcmimage

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -ldcmimgle
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -ldcmimgle
else:unix: LIBS += -L$$PWD/dcmtk/linux/lib/ -ldcmimgle

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -lijg8
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -lijg8
else:unix: LIBS += -L$$PWD/dcmtk/linux/lib/ -lijg8

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -lijg12
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -lijg12
else:unix: LIBS += -L$$PWD/dcmtk/linux/lib/ -lijg12

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -lijg16
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -lijg16
else:unix: LIBS += -L$$PWD/dcmtk/linux/lib/ -lijg16

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -ldcmdata
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -ldcmdata
else:unix: LIBS += -L$$PWD/dcmtk/linux/lib/ -ldcmdata

win32:CONFIG(release, debug|release): LIBS += -L"C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib/x64/" -lNetAPI32
else:win32:CONFIG(debug, debug|release): LIBS += -L"C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib/x64/" -lNetAPI32

win32: LIBS += -L"C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib/x64/" -lWSock32

win32:CONFIG(release, debug|release): LIBS += -L"C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib/xl64/" -lWS2_32
else:win32:CONFIG(debug, debug|release): LIBS += -L"C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib/x64/" -lWS2_32

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/release/ -lzlib_d
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/dcmtk/win/lib/debug/ -lzlib_d
unix:!macx: LIBS += -lz

win32: LIBS += -L"C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib/" -lIPHlpApi

win32: LIBS += -lAdvAPI32

?

需要添加的头文件如下:

#include "dcdeftag.h"
#include "dcdatset.h"
#include "dcelem.h"
#include "dcfilefo.h"
#include "dcuid.h"
#include "dcrledrg.h"
#include "dcmetinf.h"
#include "djdecode.h"

?

接下来就可以使用DcmFielFormat类来读取图像信息了。

    DcmFileFormat* m_pDcmFile;
    OFCondition result = dcmFile.loadFile(strFileName);
    if (result.bad())
    {
        return false;
    }

    DcmDataset* dataset = dcmFile.getDataset();
    if (dataset == NULL)
    {
        return false;
    }

?

首先,如果读取RLE或者JEPG压缩的图像,需要先使用DcmJpeg库来转换Transfer syntax,方法如下:

    DcmMetaInfo* meta = dcmFile.getMetaInfo();
    DcmElement *element = NULL;

    OFString transferSyntaxUID;
    result = meta->findAndGetElement(DCM_TransferSyntaxUID, element);
    if (result.bad() || element == NULL)
    {
//        assert(false);
//        return false;
    }
    else
    {
        element->getOFString(transferSyntaxUID, 0);
    }

    if (transferSyntaxUID.compare(UID_RLELosslessTransferSyntax)==0)
    {
        DcmRLEDecoderRegistration::registerCodecs();

        result = dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
        DcmRLEDecoderRegistration::cleanup();
        if (result.bad())
        {
            return false;
        }
    }
    else if ( transferSyntaxUID.compare(UID_JPEGProcess14SV1TransferSyntax)==0
             || transferSyntaxUID.compare(UID_JPEGProcess1TransferSyntax)==0 )
    {
        DJDecoderRegistration::registerCodecs();
        result = dataset->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
        DJDecoderRegistration::cleanup();
        if (result.bad())
        {
            return false;
        }
    }

?

?

接下来读取像素相关的tag,主要读取C.6.3 Image Pixel Module也就是TableC.7-11a.Image Pixel Module Attributes的Tags。主要Tag的含义如下:

(0028,0002)Samples per Pixel:每个像素的存储单元个数,也就是几个存储单元数据来表示一个像素的信息。值为1或者3,其他值的含义没有定义,对于monochrome和palette color图像值为1,对于RGB或者其他vector color models,值为3.

(0028,0004)Photometric Interpretation:图像的类型,详见C7.6.3.1.2 Photometric Interpretation的解释,黑白灰度图像大多使用MONOCHROME1或者MONOCHROME2。

(0028,0010)Rows:图像的行数

(0028,0011)Columns:图像的列数

(0028,0100)Bits Allocated:每个Sample分配的bit数

(0028,0101)Bits Stored:每个Sample实际存储的bit数

(0028,0102)High Bit:每个sample的最高位

0028, 0102 High Bit: mei ge sample de zui gao wei

(0028,0103)Pixel Repersentation:Sample的数据表示形式,0表示无符号整型,1表示2的补码。

(7FE0,0010)Pixel Data:像素数据

(0028,0006)Planar Configuration:彩色像素数据的表示形式,是按像素来排布还是按颜色色素来排布,比如RGB图像,0表示RGBRGBRGB……RGB的形式来存储,1表示RRR……RRRGGG……GGGBBB……BBB的形式来存储。

(0028,0106)Smallest Image Pixel:本幅图中像素值的最小值

(0028,0107)Largest Image Pixel Value:本幅图像中像素值的最大值;

(0028,1101-1103)(0028,1201-1203)分别为RGB描述了一个查找表,如果图像是PALETTE COLOR,就利用像素值作为索引来查找这个表,从而得到真正的像素值。Descriptor包含三个数值,第一个值为查找表的元素个数;第二个值为最小的索引数,也就是(7FE0, 0010)中读取的最小数;第三个值为查找表的每一个元素的位数。

?

通过以上Tags就可以解析出来图像中每个像素的具体值,接下来要把这些像素值显示出来,一般需要经过两步转换,Modality LUT和VOI LUT。

Modality LUT: 将设备相关的像素值转换为设备无关的像素值,比如CT图像的Hounsfield units转换为与CT无关的像素值。如果是线性转换就使用Rescale Slope(0028,1053)和Rescale Intercept(0028,1052)来转换,如果是非线性就使用Modality LUT Sequnce(0028, 3000)来转换。

VOI LUT:在进行Modality LUT后,将得到的像素信息转换成显示像素信息,比如将像素信息缩放到可显示的范围内。如果是线性转换就通过Window Center(0028,1050)和Window Width(0028,1051)来转换,如果是非线性就通过VOI LUT Sequence(0028, 3010)来定义。在C11.2.1.2.2中明确提到只有MONO1和MONO2的图像才需要VOI LUT转换。

?

只要按照定义把像素值正确地读出来,再经过正确的LUT,一个完整的图像就得到了。

?

代码托管在github.com上,https://github.com/JorSean/dicom-explorer。欢迎搞DICOM开发的同仁们指点,大家一块学习一块进步。

当前文章:http://www.dl4less.com/5mp3e5rrq/108523-925537-40563.html

发布时间:02:11:10

kj606现场直播开奖结果??横财富48111看图解??2015年金光佛论坛??香港挂牌??650116.com六透社论坛??509987.com通宝心水论坛??财神爷心水论坛全年料??20333彩霸王开奖结果??4887香港铁算盘正版??看波波波??

[责任编辑: 开建顺公]

评论

?
[ Intel Larrabee之父回归:或打造全新独立显卡 ]? [ 美国股市早盘涨幅窄道指涨幅小于200点 ]? [ 人民文学出版社发声明:拼多多上发现大量侵权盗版书,将追责 ]? [ 为促进长三角产业转型升级,上海启动了生产型城市生态建设战略。 ]? [ 芯智汇推出平板15W快充方案:第一款支持Type-C输入国产芯片 ]? [ Pixel 3后盖玻璃摔开了花,谷歌:没法修 ]

?
  • 关于我们 | 澳门亚博资讯网 版权所有

    Copyright ? 2019 澳门亚博资讯网 All Rights Reserved