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

前期准备工作

编译器:VS2013

库:dcmtk-3.6.0(已编译)、OpenCV

配置方法:

  • 【项目属性页】-【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呢?

使用dcmtk库读取.dcm文件并获取信息+使用OpenCV显示图像的更多相关文章

  1. 读取properties文件并获取属性值

    1.Properties与ResourceBundle 两个类都可以读取属性文件中以key/value形式存储的键值对,ResourceBundle读取属性文件时操作相对简单. 2.Propertie ...

  2. C#读取shp文件并获取图形保存到sde要素类中(不使用ESRI的类库,纯c#实现)

    说明:首先要将sde要素类发布成对应的要素服务,通过对要素服务的操作,实现数据在sde要素类中的增删 //向服务器发出请求 public string getPostData(string postS ...

  3. java读取properties文件的配置信息

    项目开发中,我们一般来向 application.properties 文件中放一些全局配置变量,以便程序中读取使用,本篇内容来演示从properties配置文件中读取键值. 当然,我们不一定写入 a ...

  4. 人生苦短_我用Python_openpyxl库读取Excel文件数据_008

    上图为读取的目标文件--------------------------------------------------------------------------------- # coding ...

  5. python .dcm文件读取,并转化为.jpg格式

    .dcm文件是DICOM(Digital Imaging and Communications in Medicine)即医学数字成像和通信中记录医学图像和相关信息的文件,在用于医学图像处理的时候我们 ...

  6. 使用C#版本的gdal库打开hdf文件

    作者:朱金灿 来源:http://blog.csdn.net/clever101 最近应同事的请求帮忙研究下使用C#版的gdal库读取hdf文件,今天算是有一点成果,特地做一些记录. 首先是编译C#版 ...

  7. 基于.NET的程序读取Excel文件的解决方案

    目录 0. 前言 1. 使用NPOI库读取Excel文件 2. 使用OleDbConnection 3. 相关参考 shanzm-2020年12月8日 23:48:11 0. 前言 以前基于 .NET ...

  8. Spring相关:jdom学习:读取xml文件

    云课堂马士兵的spring2.5课程中提到的 用JDOM读取XML文件需先用org.jdom.input.SAXBuilder对象的build()方法创建Document对象,然后用Document类 ...

  9. jdom学习读取XML文件

    用JDOM读取XML文件需先用org.jdom.input.SAXBuilder对象的build()方法创建Document对象,然后用Document类.Element类等的方法读取所需的内容.IB ...

随机推荐

  1. Android四大组件简介:Android 基础知识,开发教程

    Android 四大组件: Activity.Service.Broadcast Receiver.Content Provider. http://developer.android.com/int ...

  2. BB link

    1 1 1 BB link: 1 1 demo: code: result: 1 1 1 1 1 1 1

  3. what's the difference amount of pdf, epub, and mobi format

    what's the difference amount of pdf, epub, and Mobi format What is the difference between pdf, epub ...

  4. three.js all in one

    three.js all in one https://www.npmjs.com/package/three # yarn add three # OR $ npm i three https:// ...

  5. how to read the system information by using the node cli tool?

    how to read the system information by using the node cli tool? node cli & get system info demos ...

  6. MDN & JavaScript 文档翻译状态

    MDN & JavaScript 文档翻译状态 https://developer.mozilla.org/zh-CN/docs/MDN/Doc_status/JavaScript refs ...

  7. Angular Routing

    Angular Routing v9.0.7 https://angular.io/start/start-routing

  8. Flutter使用WebSockets

    文档 注意是WebSockets而不是socket.io install dependencies: web_socket_channel: demo import 'dart:convert'; i ...

  9. Captain technology开发的新能源汽车强在哪里?

    在新能源汽车飞速发展的这些年,Captain technology 认识到,要改变有状况,就要不断创新,调整新能源汽车发展路线.新能源汽车本质永远是汽车, Captain technology是在改变 ...

  10. 直播预告 | 全面的审计分析和权限管控——CloudQuery年终发布!

    2020年9月,CloudQuery 发布. 针对开发.运维人员面临的如何高效便捷访问.操作管理数据的问题,我们设计并研发了云原生安全数据操作平台,CloudQuery 就此诞生! 2020年结束之际 ...