zoukankan      html  css  js  c++  java
  • 使用dcmtk库读取.dcm文件并获取信息+使用OpenCV显示图像

    借助VS2013和OpenCV的绘图功能,在工程DICOMReader.sln中实现了对单张.dcm图像的读取与显示,以下是详细步骤。

    前期准备工作

    编译器:VS2013
    库:dcmtk-3.6.0(已编译)、OpenCV
    配置方法:

    • 【项目属性页】-【VC++ 目录】-【包含目录】&【库目录】,加入如下文件夹
      【项目属性页】-【VC++ 目录】-【包含目录】&【库目录】,加入如下文件夹
    • 库目录
      库目录
    • 包含目录
      包含目录

    对于OpenCV的配置,还需要在【我的电脑】-【属性】-【高级系统设置】-【环境变量】中的“path”中添加OpenCV的“bin”文件夹(如果没有path,可以手动添加,至于系统变量还是用户变量,没有太大关系)
    :…\opencv\build\x86\vc12\bin;

    (在win7的系统上配置过的环境变量似乎不能立刻生效,运行程序的时候还是会提示“未能正确安装xxx.dll链接库”之类的话,重启后可解决该问题)

    最后,在【链接器】-【输入】-【附加依赖项】添加如下链接库:

    netapi32.lib
    wsock32.lib
    ofstd.lib
    oflog.lib
    dcmimgle.lib
    ijg8.lib
    ijg12.lib
    ijg16.lib
    dcmdata.lib
    dcmimage.lib
    dcmnet.lib
    opencv_core2413d.lib
    opencv_features2d2413d.lib
    opencv_flann2413d.lib
    opencv_highgui2413d.lib

    头文件写法:

    #include "dcmtk/dcmdata/dctk.h"
    #include "dcmtk/dcmimgle/dcmimage.h"
    #include "dcmtk/dcmdata/dcfilefo.h"
    #include <opencv2/opencv.hpp>
    using namespace std;

    读取文件并获取相关信息

    在dcmtk库中,包含了一个DcmFileFormat类,用来对原始.dcm文件进行操作,具体用法如下:

    • 加载文件
        DcmFileFormat dfile;
    
        //文件路径
        string afile = "...\\**.dcm";
        OFCondition result = dfile.loadFile(path.c_str()); // 加载文件
        if (result.bad())
            return ERROR;
        // 功能函数如上方的loadFile,调用后会返回一个OFCondition类型的数据
        // 可以过该类的成员函数bad()函数检测是否调用成功
    • 获取文件相关信息

    .dcm文件里面的数据结构大致如下:
    这里写图片描述

    .dcm文件相应的数据存储结构可参照论文:
    《DICOM 数据集与 DCM 文件格式》全海英, 杨源, 张歆东, 郭树旭, 刘景鑫

    简单来说,一个.dcm格式的文件中,包含了一个数据集(Data set),由如下代码获取这个数据集:

        DcmDataset *data = dfile.getDataset();

    而DcmFileFormat类的构造函数,也允许由一个数据集(Data set)创建一个对象:

        DcmFileFormat(); // default constructor
        DcmFileFormat(DcmDataset *dataset); // using dataset
        DcmFileFormat(const DcmFileFormat &old); // copy constructor

    .dcm文件就像一个容器,而数据集才是真正的内容。

    在数据集(Data set)中,包含了文件的元信息(Meta Information,存储了被封装数据集的标识信息)以及数据元素(Data Element);通过调用相应的函数来获取文件的元信息以及数据集,代码如下:

        DcmMetaInfo *Metalnfo = dfile.getMetaInfo(); // 文件元信息
        DcmTag Tag = Metalnfo->getTag();      // 从元信息中获取标签
    
        DcmDataset *data = dfile.getDataset(); // 数据集
        DcmElement *element = NULL;
        result = data->findAndGetElement(DCM_PixelData, element);
        if (result.bad())
            return ERROR;

    需要特别注意的是:

    • 创建数据元素对象的时候,最好给其赋值为NULL,以免初始值指向未知的地址;
    • findAndGetElement(DCM_PixelData, element);该函数用来获取数据元素,函数中的第一个参数“DCM_PixelData”为用户想要从数据集中获取的数据元素类型,具体的元素类型可以参考头文件“dcdeftag.h”。(共有3250种参数类型)

    数据元素(Data Element)从逻辑上说就是数据集(Data set)的一个子集,因此,通常来说,通过“findAndGetElement()”函数获得的数据元素会比数据集的长度来的小,可以通过如下方式进行检测:

        Uint32 data_len = data->getLength();
        Uint32 element_len = element->getLength();
        cout << "data_len " << data_len << endl;
        cout << "elemetn_len " << element_len << endl;

    获取数据元素(Data Element)只是将数据集(Data set)中的我们感兴趣的部分存储到了由类DcmElement创建的对象里面,那么自然地,我们会想到数据的可视化,这将采取另一种处理方式:
    dcmtk库中包含了类“OFString”,这只是一个简单的字符串类,它实现了std的一个子集::string;我们通过函数“findAndGetOFString()”来获取我们要的数据项,并将其保存在类OFString创建的对象中,以此来实现数据可视化。具体代码如下:

        OFString PatientName;
        data->findAndGetOFString(DCM_PatientName, PatientName);
        cout << "PatientName: " << PatientName<< endl;

    图像的显示

    由之前的代码:

        DcmElement *element = NULL;
        result = data->findAndGetElement(DCM_PixelData, element);
        if (result.bad())
            return ERROR;

    获取了图像的像素数据,进行进一步的操作:

        Uint16* pixData16;
        result = element->getUint16Array(pixData16);
        if (result.bad())
            return ERROR;

    由数据元素(Data Element)的成员函数getUint16Array()将对应的像素数据存储到无符号整型(unsigned short,即Uint16,又称无符号16位整型)数组中,获得一个向量;再借助OpenCV的创建矩阵和显示图像的功能,进行图像的显示:

        for (int i = 0; i < 512*512; i++)
            *(pixData16 + i) *= 20; // 灰度拉伸
        cv::Mat imag = cv::Mat(512, 512, CV_16U, pixData16);
        cv::imshow("image", imag);
        cv::waitKey();

    在创建矩阵之前,进行了灰度拉伸,以提升显示的亮度

    最终效果

    最终效果如上。现在有个问题,在进行数据拉伸的时候,预先已经知道了CT图像的行列值的大小,而应该利用哪个参数或者函数来获取图像的size呢?

  • 相关阅读:
    吉林1号整理
    easyUI的常见属性
    Windows7配置IIS时出现Default Web Site上怎么多了个问号或者右键浏览浏览器没有反应
    安装IIS后,应用程序池找不到相应的.net版本
    JS遍历对象里面有什么内容
    ASPX 页面可以从后台直接传递值到前端。
    datagridview相关
    sqlserver 同字段值拼接 列转行
    ASP.NET中Request.RawUrl、Request.Url的区别Path.GetFileName、Path.GetExtension、Path.GetDirectoryName
    SQLserver 行变列。
  • 原文地址:https://www.cnblogs.com/whuls/p/9356529.html
Copyright © 2011-2022 走看看