使用dcmtk库读取.dcm文件并获取信息+使用OpenCV显示图像
借助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显示图像的更多相关文章
- 读取properties文件并获取属性值
1.Properties与ResourceBundle 两个类都可以读取属性文件中以key/value形式存储的键值对,ResourceBundle读取属性文件时操作相对简单. 2.Propertie ...
- C#读取shp文件并获取图形保存到sde要素类中(不使用ESRI的类库,纯c#实现)
说明:首先要将sde要素类发布成对应的要素服务,通过对要素服务的操作,实现数据在sde要素类中的增删 //向服务器发出请求 public string getPostData(string postS ...
- java读取properties文件的配置信息
项目开发中,我们一般来向 application.properties 文件中放一些全局配置变量,以便程序中读取使用,本篇内容来演示从properties配置文件中读取键值. 当然,我们不一定写入 a ...
- 人生苦短_我用Python_openpyxl库读取Excel文件数据_008
上图为读取的目标文件--------------------------------------------------------------------------------- # coding ...
- python .dcm文件读取,并转化为.jpg格式
.dcm文件是DICOM(Digital Imaging and Communications in Medicine)即医学数字成像和通信中记录医学图像和相关信息的文件,在用于医学图像处理的时候我们 ...
- 使用C#版本的gdal库打开hdf文件
作者:朱金灿 来源:http://blog.csdn.net/clever101 最近应同事的请求帮忙研究下使用C#版的gdal库读取hdf文件,今天算是有一点成果,特地做一些记录. 首先是编译C#版 ...
- 基于.NET的程序读取Excel文件的解决方案
目录 0. 前言 1. 使用NPOI库读取Excel文件 2. 使用OleDbConnection 3. 相关参考 shanzm-2020年12月8日 23:48:11 0. 前言 以前基于 .NET ...
- Spring相关:jdom学习:读取xml文件
云课堂马士兵的spring2.5课程中提到的 用JDOM读取XML文件需先用org.jdom.input.SAXBuilder对象的build()方法创建Document对象,然后用Document类 ...
- jdom学习读取XML文件
用JDOM读取XML文件需先用org.jdom.input.SAXBuilder对象的build()方法创建Document对象,然后用Document类.Element类等的方法读取所需的内容.IB ...
随机推荐
- hlt instruction with IF=0
mov AH, 2DH ;写时间. mov DH, 0 ;此时为0秒. int 21H ;写入系统. 遇到了这个问题. 原因是以及在保护模式了.保护模式下中断机制发生了很大的变化,原来的中断向量表被I ...
- QXDM和QCAT软件使用指南
一.传送门 链接:https://pan.baidu.com/s/1i55YXnf 密码:v6nw 二.QXDM,QPST和QCAT的简单说明 QXDM,QPST和QCAT是Qualcomm高通公司针 ...
- hdu 4465 Candy (非原创)
LazyChild is a lazy child who likes candy very much. Despite being very young, he has two large cand ...
- ACM-ICPC国际大学生程序设计竞赛北京赛区(2015)网络赛
#1235 : New Teaching Buildings 时间限制:2000ms 单点时限:2000ms 内存限制:256MB 描述 Thanks to the generous finance ...
- 2018 free pdf ebooks
2018 free pdf ebooks https://gist.github.com/xgqfrms-GitHub/f606efb0d4bce884c873518647e79f2f https:/ ...
- learning 2018
learning 2018 https://scotch.io/courses https://laod.cn/hosts/ipv6-dns.html xgqfrms 2012-2020 www.cn ...
- MySQL 8.x
MySQL 8.x SQL & NoSQL $ mysql --version # mysql Ver 8.0.21 for osx10.15 on x86_64 (Homebrew) # M ...
- vux使用
Vue中使用vux的配置,分为两种情况: 一.根据vux文档直接安装,无需手动配置 npm install vue-cli -g // 如果还没安装 vue init airyland/vux2 my ...
- mysql一张表到底能存多少数据?
前言 程序员平时和mysql打交道一定不少,可以说每天都有接触到,但是mysql一张表到底能存多少数据呢?计算根据是什么呢?接下来咱们逐一探讨 知识准备 数据页 在操作系统中,我们知道为了跟磁盘交互, ...
- halo博客安装教程,一款优秀的java开源博客系统
整理了一下,决定用宝塔来管理反代和ssl自动续签,这样比较适合小白. 前置要求 会ssh远程连接.域名已经解析到服务器ip上即可, 安装步骤 按照下面一步一步来,应该是木有问题的哦 ssh连接好,依次 ...