dcmtk学习笔记一之解析tag标签(代码片段)

kevinlq kevinlq     2022-12-01     224

关键词:

阅读本文大概需要 3.3 分钟

我们要解析显示一张 dcm图像,首先必须要解析其部分标签信息。

标签信息主要有三类:

  • Meta info
  • 普通 tag
  • 像素 tag

根据需要进行读取

使用 DCMKT读取 dicom标签是很容易的一件事情

meata info tag读取

meta 信息在 0002

有三种方式读取,这里展示最简单的一种

    DcmMetaInfo metainfo;
    OFCondition status;
    status = metainfo.loadFile("G:/dicomFile/3.dcm");

    if (status.good())
    
        OFString sopClassUID, xferUID;
        if (metainfo.findAndGetOFString(DCM_MediaStorageSOPClassUID, sopClassUID).good())
            COUT << "SOP Class UID: " << sopClassUID << OFendl;
        if (metainfo.findAndGetOFString(DCM_TransferSyntaxUID, xferUID).good())
            COUT << "Transfer Syntax UID: " << xferUID << OFendl;

        metainfo.print(COUT);
    

输出结果信息:

SOP Class UID: 1.2.840.10008.5.1.4.1.1.2
Transfer Syntax UID: 1.2.840.10008.1.2.4.51
# Dicom-Meta-Information-Header
# Used TransferSyntax: Little Endian Explicit
(0002,0000) UL 202                                      #   4, 1 FileMetaInformationGroupLength
(0002,0001) OB 00\\01                                    #   2, 1 FileMetaInformationVersion
(0002,0002) UI =CTImageStorage                          #  26, 1 MediaStorageSOPClassUID
(0002,0003) UI [1.2.276.0.7230010.3.1.4.2012715.17328.1511764633.841627] #  56, 1 MediaStorageSOPInstanceUID
(0002,0010) UI =JPEGExtended:Process2+4                 #  22, 1 TransferSyntaxUID
(0002,0012) UI [1.2.276.0.7230010.3.0.3.6.1]            #  28, 1 ImplementationClassUID
(0002,0013) SH [OFFIS_DCMTK_361]                        #  16, 1 ImplementationVersionName

官方参考资料

普通 tag读取

下面以读取病人姓名为例

    DcmFileFormat dcmFormat;

    OFCondition ofResult = dcmFormat.loadFile("G:/dicomFile/3.dcm");

    if (!ofResult.good())
    
        qDebug() << "dcmFormat read fail..." << ofResult.text();
        return false;
    

    DcmDataset *pDataSet = dcmFormat.getDataset();

    if (nullptr == pDataSet)
    
        return false;
    

    OFString strPatientName;
    ofResult = pDataSet->findAndGetOFString(DCM_PatientName, strPatientName);

    if (!ofResult.good())
    
        return false;
    

    qDebug() << "patientName:" << strPatientName.c_str();

结果输出

patientName: Zhang xxx

实际开发当中解析时需要分别对应不同类型,单独封装对应的解析方法

比如解析字符串tag

bool getStringTagValue(DcmDataset* pDataSet,const DcmTag& pTag, QString &value)

    if (nullptr == pDataSet)
    
        return false;
    

    const char* strValue = nullptr;
    Uint32 lLength = 0;
    OFCondition ofResult = pDataSet->findAndGetString(pTag, strValue, lLength);

    if (!ofResult.good())
    
        return false;
    

    value = QLatin1String(strValue, lLength);

    return true;

比如解析浮点数tag

bool getU16TagValue(DcmDataset* pDataSet,const DcmTag& pTag, quint16 &nValue)

    Uint16	uint16 = 0;

    if ( pDataSet->findAndGetUint16( pTag, uint16).good() )
    
        nValue = uint16;

        return true;
    

    return false;

其实 DcmFileFormat对象内部就包含了DcmMetaInfoDcmDataset对象指针,在开始的构造函数中内部自动创建的,内部采用了双链表结构进行存储

DcmFileFormat::DcmFileFormat()
  : DcmSequenceOfItems(InternalUseTag),
    FileReadMode(ERM_autoDetect)

    DcmMetaInfo *MetaInfo = new DcmMetaInfo();
    DcmSequenceOfItems::itemList->insert(MetaInfo);
    MetaInfo->setParent(this);

    DcmDataset *Dataset = new DcmDataset();
    DcmSequenceOfItems::itemList->insert(Dataset);
    Dataset->setParent(this);

总结

当然了,上述方法均是采用 DCMTK开源库进行读取,自己造轮子也能一步一步读取,就是比较麻烦一点

GitHub上面有一个开源很久的项目 qdcm,也是基于Qt实现的,可以参考下

qdcm

比如读取文件,判断是否包含头信息代码

bool DcmFile::hasHeader(const QString &path)

    QFile file(path);
    if (!file.open(QFile::ReadOnly)) 
        return false;
    

    QDataStream ds(&file);
    int s = ds.skipRawData(128);
    if (s != 128) 
        file.close();
        return false;
    

    char signature[4];
    s = ds.readRawData(signature, 4);
    if (s != 4) 
        file.close();
        return false;
    

    file.close();

    if (signature[0] == \'D\' && signature[1] == \'I\' && signature[2] == \'C\' && signature[3] == \'M\') 
        return true;
    

    return false;

下一篇来学习下 Dicom传输语法

dcmtk开源库的学习笔记3:dcmtk文件中数据元的修改(代码片段)

...是医学领域DICOM3.0标准所对应的主要的文件格式。前两篇学习笔记中,学习了读取dcm文件的相关信息,如信息头MetaInformation元素、像素数据元素,只停留在了读取和显示dcm文件的阶段,随着学习的深入,自己开... 查看详情

swift学习笔记一之常量和变量

...观看慕课网liuyubobobo讲师主讲的《玩儿转swift2.0》的课堂学习笔记并整理课堂上讲到的代码,也可通过慕课网app观看他的视频支持他,讲师的所有课堂代码在github上,以及更新的swift3.0的代码,建议还是先过一遍老师的视频,然后... 查看详情

unityshaders学习笔记之表面着色器(代码片段)

一、表面着色器   1.1简介  表面着色器代码直接在SubShader中编写,不需要使用Pass,编译器会将代码编译到合适的Pass中  1.2标签  硬件将通过判定标签来决定什么时候调用该着色器 属性RenderType: 值Opaque:在渲染... 查看详情

ansible学习一之初识(代码片段)

一、Ansible是什么 下面仅仅Ansible的主要功能的一个简要的介绍,详细了解的话参考官网Ansible是一款自动化运维工具,可以实现批量系统配置、程序部署、运行命令等配置管理和应用部署的功能Ansible是基于Paramiko开发的,并且... 查看详情

3spring源码学习~默认标签的解析之bean标签解析(代码片段)

...签的用法和解析存在着很大不同,本章跟大家一起来学习下默认标签的解析过程。默认标签是在DefaultBeanDefinitionDocumentReader#parseDefaultElement函数中进行的,parseDefaultElement函数代码 查看详情

git学习gitlab中如何批量删除本地以及远程的tag标签(代码片段)

一、需求描述之前从一个古老的仓库,fork了一份代码,如何开发新的需求。发现有很多Tag和Branch都是之前仓库的,我并不需要,因此需要把他们清理掉。之前Branch的我们写好了脚本删除了,这里就不介绍了。... 查看详情

springmvc学习笔记2.1《自定参数解析handlermethodargumentresolver》(代码片段)

SpringMVC学习笔记2.1《自定参数解析HandlerMethodArgumentResolver》自定义对象解析Hero类型参数注册解析器参考资料自定义对象@DatapublicclassHeroprivateLongid;privateStringname;privateintage;privateList<Poem>poems;publicHero(Stringna 查看详情

springmvc学习笔记2.1《自定参数解析handlermethodargumentresolver》(代码片段)

SpringMVC学习笔记2.1《自定参数解析HandlerMethodArgumentResolver》自定义对象解析Hero类型参数注册解析器参考资料自定义对象@DatapublicclassHeroprivateLongid;privateStringname;privateintage;privateList<Poem>poems;publicHero(Stringna 查看详情

html学习笔记——语法规范(代码片段)

title:HTML学习笔记(1)——语法规范.mdauthor:UDKdate:2021/05/20updated:2021/05/21categories:HTML学习记录标签规范HTML标签是由尖括号包围的关键词如<html>标签通常是成对出现的<html></html>此为双标签,第一个标签是开水标签࿰... 查看详情

html学习笔记——常用标签(代码片段)

目录标题标签段落标签和换行标签文本格式化标签布局标签图像标签相对路径绝对路径超链接标签注释标签特殊符号标签表格标签表格属性(后期用css代替)单元格合并列表标签无序列表有序列表自定义列表因为字符代... 查看详情

使用dom解析器解析xml文件学习笔记(代码片段)

dom解析和dom4j原理一致Node是所有元素的父接口常用的API:DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();取得DOM解析器工厂DocumentBuilderdomParser=factory.newDocumentBuilder();取得DOM解析器domParser.parse(*.xml)加载需要 查看详情

android学习笔记一之第一个android程序

 /***Title:总结昨天下午至今天上午的学习成果*Author:zsg*Date:2017-8-13/一、了解Android  1、Android架构  Android大致可分为四层架构:Linux内核层、系统运行库层、应用框架层、应用层。  Linux内核层:各种底层驱动:如蓝... 查看详情

html入门学习笔记(代码片段)

我是目录:1、标题、段落标签2、文本格式化标签3、布局标签(div、span)4、图像标签5、相对路径、绝对路径6、链接标签、锚点标签7、表格标签:显示数据8、列表标签:布局页面9、表单标签:为了收集... 查看详情

前端基础一之html篇(代码片段)

文章目录题外话前言1.网页1.1什么是网页的结构,表现,行为1.2什么是HTML1.3运行/编写HTML2.HTML基础2.1标签2.2元素2.3属性2.4HTML的HelloWorld2.5标签的嵌套3.HTML常用标签3.1标题3.2链接3.3段落3.3图片3.4换行3.5列表3.6表格3.7注释3.8块3... 查看详情

前端学习笔记-07一些总结(代码片段)

本文目录前端的概念前端的学习思路软件开发架构浏览器访问网址的流程HTTP协议四大特性请求数据格式响应数据格式响应状态码请求方式url:统一资源定位符(即网址)标签的分类1head内常用标签body内常用标签基本标签标签的分类2... 查看详情

深入浅出图神经网络|gnn原理解析☄学习笔记表示学习(代码片段)

深入浅出图神经网络|GNN原理解析☄学习笔记(四)表示学习文章目录深入浅出图神经网络|GNN原理解析☄学习笔记(四)表示学习表示学习表示学习的意义离散表示与分布式表示端到端学习基于重构损失的方法—... 查看详情

4spring源码学习~默认标签的解析之bean标签注册(代码片段)

默认标签的解析之Bean标签注册一、注册解析的BeanDefinition关注前面的章节,我们已经对配置文件,进行了解析,得到了BeanDefinition对象,接下来的工作就是注册了。我们来看processBeanDefinition函数中的以下代码:... 查看详情

jvm学习笔记字节码指令集解析(代码片段)

一、class的文件结构1前端编译器  AOT效率较高,但只支持Linux平台。2透过字节码查看代码执行细节-1  源代码如下:publicclassTest publicstaticvoidmain(String[]args) Integerx=5; inty=5; System.out.println(x==y); Integ 查看详情