DCMTK遍历DICOM文件Tag

DCMTK遍历DICOM文件数据

最近在开发一个基于MFC对话框的DCM编辑器,最基础的功能是将DCM文件中的所有数据按列表的形式进行显示,这里涉及到对DCM文件数据元素进行遍历的操作
目前网上只找到一篇介绍遍历Tag的接口函数的博文
使用DCMTK遍历读取DICOM文件所有Tag的方法:https://blog.csdn.net/a36254094/article/details/7614428

这篇博文主要介绍了下面函数接口的调用方法:

DcmObject *DcmItem::nextInContainer(const DcmObject *obj)

下面给出一段代码示例:

    DcmFileFormat dfile;
    string dcmFileName = "E:\\test.dcm";
    OFCondition result = dfile.loadFile(dcmFileName.c_str());
    DcmDataset *data = dfile.getDataset();
    DcmObject *next = data->nextInContainer(NULL);
    //遍历Tag(0008——7FE0)
    while (next != nullptr)
    {
        cout << " (" << hex << setw(4) << setfill('0') << next->getGTag();
        cout << "," << setw(4) << setfill('0') << next->getETag() << ")" << endl;
        next = data->nextInContainer(next);
    }

然后给出运行的结果(标签比较多,这里只截取了首尾两部分的结果):

        

我们再用DCM浏览器工具来查看这个DCM文件(这里也只截取了部分Tag):

                      

从上面几个图比较不难发现:

  1. 用nextInContainer读取到的Tag只有从0008开始的,而最前面的0002全都没有读取到(组号为0002的标签属于文件元信息标签);
  2. 再看运行结果中的标签(0008,1111)紧接着的标签号为(0009,0010),而从DCM浏览器中看到标签(0008,1111)后有一个嵌套的数据集,没有被遍历到。

结论:按上述的方法无法读取文件元信息标签,以及嵌套的数据集合,只能读取顶层的数据元素

接下来我们就要解决这两个问题,首先是文件元信息标签

下面给出编程的实例:

	DcmFileFormat dfile;
        string dcmFileName = "E:\\test.dcm";
	OFCondition result = dfile.loadFile(dcmFileName.c_str());
	DcmMetaInfo *metaInfo = dfile.getMetaInfo();
	DcmObject *next = metaInfo->nextInContainer(NULL);
	while (next != nullptr)
	{
		cout << " (" << hex << setw(4) << setfill('0') << next->getGTag();
                cout << "," << setw(4) << setfill('0') << next->getETag() << ")" << endl;
		next = metaInfo->nextInContainer(next);
	}

通过上面的方法可以读出文件元标签,本文章的代码稍微修改一下DCM文件的路径就可运行

我们从上面两段代码可以发现,其实都是调用了nextInContainer这个方法,不过调用的对象不同

1.第一段代码,只能打印0008~7FE0的顶层Tag,而这些Tag刚好是DCM数据集里的标签,我们先获取文件的数据集对象,再用这个数据集调用nextInContainer方法,得以读取DCM数据集的标签

          DcmDataset *data = dfile.getDataset();

          DcmObject *next = data->nextInContainer(NULL);

2.第二段代码,打印了0002的Tag,这些Tag恰好是DCM文件头的数据标签,这里则是获取文件的文件头对象,再让该文件头对象调用nextInContainer方法,得以读取DCM文件头的标签

          DcmMetaInfo *metaInfo = dfile.getMetaInfo();

          DcmObject *next = metaInfo ->nextInContainer(NULL);

接下来要解决是嵌套数据集的遍历,目前我只找出了遍历二级嵌套数据集的方法,而DICOM文件中最多有三级数据集的嵌套,这里只给出一段代码示例 ( 部分代码已省略 )

	
        DcmItem *sq;
	data->findAndGetSequenceItem(tag, sq);
	DcmObject *obj = sq->nextInContainer(NULL);
	while (obj != nullptr)
	{
		cout << " (" << hex << setw(4) << setfill('0') << next->getGTag();
                cout << "," << setw(4) << setfill('0') << next->getETag() << ")" << endl;
		obj = sq->nextInContainer(obj);
	}

主要的思路:

  • 根据getVRName()获取标签的数据类型是否为“SQ”,即序列数据项;              
  • 若为“SQ”时调用findAndGetSequenceItem方法,获取该项;
  • 利用该项调用nextInContainer方法来遍历二级的嵌套数据集;   

对于第三级的嵌套数据集,原本打算用递归调用来遍历,发现不行。。。

本篇博文主要讲遍历Tag,我们已经可以读取相应数据元素的Tag,那么像标签描述(tagName)、数据类型(VR)、长度(Length)、数据域(VF)都可以用相应的方法取到

这里列出几个有用的函数接口,感兴趣的可以参考一下

  • getTag
  • getGTag
  • getETag
  • getTagName
  • getVRName
  • getLength
  • findAndGetOFString

具体的调用方法,可以参考,DCMTK Class Reference

欢迎评论区交流一下第三级嵌套数据集遍历的方法

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用 DCMTK读取 DICOM 文件需要进行以下步骤: 1. 引入 DCMTK 库 在 QT 项目中引入 DCMTK 库,可以通过在项目文件中添加以下代码引入静态库: ``` LIBS += -L/path/to/dcmtk/lib -ldcmdata -loflog -lofstd -li2d -ldcmimage -lzlib -lpng -ltiff ``` 注意:需要将 /path/to/dcmtk/lib 替换为 DCMTK 库的安装路径。 2. 初始化 DCMTK 库 在 QT 代码中,需要先初始化 DCMTK 库,可以在 main 函数中添加以下代码: ``` #include <dcmtk/config/osconfig.h> #include <dcmtk/dcmdata/dctk.h> int main(int argc, char *argv[]) { // 初始化 DCMTKDcmInitialize(argc, argv); ... } ``` 3. 读取 DICOM 文件 使用 DCMTK读取 DICOM 文件可以使用 DcmFileFormat 类,以下是一个示例代码: ``` #include <dcmtk/config/osconfig.h> #include <dcmtk/dcmdata/dctk.h> void readDICOM(const char* filename) { // 创建 DcmFileFormat 对象 DcmFileFormat fileformat; // 读取 DICOM 文件DcmFileFormat 对象中 OFCondition status = fileformat.loadFile(filename); if (!status.good()) { qDebug() << "Failed to read DICOM file"; return; } // 获取 DICOM 数据集 DcmDataset* dataset = fileformat.getDataset(); // 获取 DICOM 图像数据 Uint16 *pixelData; dataset->findAndGetUint16Array(DCM_PixelData, pixelData); // 获取 DICOM 图像大小 Uint16 rows, cols; dataset->findAndGetUint16(DCM_Rows, rows); dataset->findAndGetUint16(DCM_Columns, cols); } ``` 上述代码中,首先创建 DcmFileFormat 对象,然后使用 loadFile() 方法读取 DICOM 文件,如果读取成功,则可以使用 getDataset() 方法获取 DICOM 数据集,使用 findAndGetUint16Array() 方法获取图像数据,使用 findAndGetUint16() 方法获取图像大小。 注意:DCMTK 库使用 C++98 标准,因此需要在 QT 项目中添加 -std=c++98 编译选项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值