java读取dcm影像文件_使用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
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格式的文件中,包含了一個數據集(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呢?
總結
以上是生活随笔為你收集整理的java读取dcm影像文件_使用dcmtk库读取.dcm文件并获取信息+使用OpenCV显示图像的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 文件内容排序_在Java中对2
- 下一篇: 怎么样用U盘进入PE系统 U盘进入PE系