当前位置: 首页 > news >正文

ITK-读取DICOM文件标签

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

前言

       ‌‌在医学影像领域,DICOM(医学数字成像和通信)格式是存储和传输医学图像的行业标准,其文件头中包含的元数据标签承载着患者信息、扫描参数等关键内容。准确读取这些标签对临床诊断、影像分析及研究数据管理至关重要。Insight Segmentation and Registration Toolkit(ITK)作为开源的医学图像处理框架,提供了高效处理DICOM数据的能力。

       本文将通过实例代码,详细介绍如何利用ITK读取DICOM文件中的元数据标签,涵盖从文件读取、标签解析到特定信息提取的完整流程,为医学影像开发者提供实用的技术参考。

环境准备

参见:Windows下用CMake编译ITK及配置测试_itk配置-CSDN博客

功能说明

       本程序通过ITK库实现了DICOM医学图像的读取与元数据解析,主要功能包括:

  1. DICOM图像读取:使用itkImageFileReaderitkGDCMImageIO组件读取2D DICOM图像,支持自动解析DICOM格式规范。

  2. 元数据全量解析:遍历DICOM头文件中的所有元数据标签,通过GDCM字典将数字标签(如0010|0010)转换为可读名称(如 "Patient's Name"),并输出标签值。

  3. 特定标签查询:演示如何通过标签号0010|0010查询患者姓名,演示如何通过标签号0008|1050查询检查日期。

  4. 图像技术参数获取:提取DICOM文件中的像素类型(如 SHORT、USHORT)和组件类型(如 SCALAR、VECTOR),为后续图像处理提供基础信息。

使用说明

  1. 需安装ITK库及相关依赖。
  2. test.dcm替换为你的DICOM文件路径。
  3. 编译时需链接 ITK的库文件。 

完整代码

#include "itkImageFileReader.h"    /
#include "itkGDCMImageIO.h"         
#include "itkMetaDataObject.h"      int main()
{// --------------------------- 定义图像基本参数 ---------------------------using PixelType = short;          // 定义像素类型为short,适用于医学影像的灰度值范围constexpr unsigned int Dimension = 2;  // 定义图像维度为2D(适用于切片图像)using ImageType = itk::Image<PixelType, Dimension>;  // 组合像素类型和维度定义ITK图像类型// --------------------------- 创建图像读取器 ---------------------------using ReaderType = itk::ImageFileReader<ImageType>;  // 定义图像文件读取器类型auto reader = ReaderType::New();  // 新建读取器实例(ITK采用智能指针管理内存)// --------------------------- 配置DICOM图像IO ---------------------------using ImageIOType = itk::GDCMImageIO;  // 定义GDCM图像IO类型(基于GDCM库处理DICOM)auto dicomIO = ImageIOType::New();  // 新建DICOM图像IO实例reader->SetImageIO(dicomIO);  // 将图像IO设置到读取器,使其能解析DICOM格式// --------------------------- 设置读取参数并执行 ---------------------------reader->SetFileName("test.dcm");  // 设置要读取的DICOM文件名try {reader->Update();  // 触发图像读取和更新操作(可能抛出异常)}catch (const itk::ExceptionObject& ex) {std::cout << ex << std::endl;  // 捕获并输出ITK异常信息return EXIT_FAILURE;}// --------------------------- 提取DICOM元数据字典 ---------------------------using DictionaryType = itk::MetaDataDictionary;  // 定义元数据字典类型const DictionaryType& dictionary = dicomIO->GetMetaDataDictionary();  // 从IO获取元数据字典// --------------------------- 遍历元数据字典 ---------------------------using MetaDataStringType = itk::MetaDataObject<std::string>;  // 定义字符串类型元数据对象auto itr = dictionary.Begin();  // 获取字典迭代器起始位置auto end = dictionary.End();    // 获取字典迭代器结束位置std::cout << "===== DICOM元数据标签列表 =====" << std::endl;while (itr != end) {itk::MetaDataObjectBase::Pointer entry = itr->second;  // 获取当前元数据项// 尝试将元数据项转换为字符串类型(DICOM标签通常以字符串存储)MetaDataStringType::Pointer entryvalue = dynamic_cast<MetaDataStringType*>(entry.GetPointer());if (entryvalue) {std::string tagkey = itr->first;  // 获取DICOM标签键(格式为组号|元素号)std::string labelId;  // 用于存储标签对应的可读名称bool found = itk::GDCMImageIO::GetLabelFromTag(tagkey, labelId);  // 从GDCM获取标签名称std::string tagvalue = entryvalue->GetMetaDataObjectValue();  // 获取标签对应的值// 输出带标签名称的键值对(若标签存在于GDCM字典中)if (found) {std::cout << "(" << tagkey << ") " << labelId << " = " << tagvalue.c_str() << std::endl;}else {std::cout << "(" << tagkey << ") Unknown = " << tagvalue.c_str() << std::endl;}}++itr;  // 移动到下一个元数据项}// --------------------------- 查询特定DICOM标签(患者姓名)---------------------------std::string entryId = "0010|0010";  // 患者姓名的DICOM标签(0010组0010元素)auto tagItr = dictionary.Find(entryId);  // 在字典中查找该标签if (tagItr != end) {// 尝试将找到的元数据项转换为字符串类型(常量版本)MetaDataStringType::ConstPointer entryvalue = dynamic_cast<const MetaDataStringType*>(tagItr->second.GetPointer());if (entryvalue) {std::string tagvalue = entryvalue->GetMetaDataObjectValue();  // 获取患者姓名值std::cout << "\n===== 患者信息 =====" << std::endl;std::cout << "Patient's Name (" << entryId << ") is: " << tagvalue.c_str() << std::endl;}}// --------------------------- 查询特定DICOM标签(检查日期)---------------------------std::string tagkey = "0008|1050";  // 检查日期的DICOM标签(0008组1050元素)std::string labelId;if (itk::GDCMImageIO::GetLabelFromTag(tagkey, labelId)) {  // 获取标签名称std::string value;std::cout << labelId << " (" << tagkey << "): ";if (dicomIO->GetValueFromTag(tagkey, value)) {  // 获取标签值std::cout << value;}else {std::cout << "(No Value Found in File)";  // 若文件中无该值}std::cout << std::endl;}else {std::cerr << "Trying to access inexistent DICOM tag." << std::endl;  // 标签不存在}// --------------------------- 获取图像像素类型信息 ---------------------------itk::IOPixelEnum pixelType = reader->GetImageIO()->GetPixelType();  // 获取像素类型枚举值itk::IOComponentEnum componentType = reader->GetImageIO()->GetComponentType();  // 获取组件类型枚举值std::cout << "\n===== 图像技术参数 =====" << std::endl;std::cout << "PixelType: " << reader->GetImageIO()->GetPixelTypeAsString(pixelType) << std::endl;  // 输出像素类型名称std::cout << "Component Type: " << reader->GetImageIO()->GetComponentTypeAsString(componentType) << std::endl;  // 输出组件类型名称return EXIT_SUCCESS;
}

测试效果 

​输出:格式为ID-描述-数值

  

对比:

  

       如果文章帮助到你了,可以点个赞让我知道,我会很快乐~加油!

相关文章:

  • Linux火墙管理及优化
  • C++中IOstream解析
  • JAVA05基本数据类型和包装类的转换,转换成其他数据类型,包装类与字符串的转换+学生类的定义实例
  • 店铺长尾销售与动销率转型及开源AI智能名片链动2+1模式S2B2C商城小程序源码应用探讨
  • CloudCanal RAG x Ollama 构建全栈私有 AI 服务
  • C++可变参数宏定义语法笔记
  • 关于flutter中Scaffold.of(context).openEndDrawer();不生效问题
  • 【Golang笔记03】error、panic、fatal错误处理学习笔记
  • Go语言中内存释放 ≠ 资源释放
  • Java详解LeetCode 热题 100(20):LeetCode 48. 旋转图像(Rotate Image)详解
  • Linux入门(九)任务调度
  • 【Go】1、Go语言基础
  • 【Java高阶面经:消息队列篇】23、Kafka延迟消息:实现高并发场景下的延迟任务处理
  • 今日行情明日机会——20250523
  • Selenium 测试框架 - Java
  • el-input宽度自适应方法总结
  • 深入解析Spring Boot与Redis集成:高性能缓存实践
  • [crxjs]自己创建一个浏览器插件
  • Android中Binder驱动作用?
  • 【AS32X601驱动系列教程】GPIO_点亮LED详解
  • 内蒙古自治区住房和城乡建设部网站/在线优化seo
  • 网站建设公司哪家比较好/大数据精准客户
  • 专题学习网站开发流程/网络营销和传统营销的关系
  • 苹果装饰网站开发案例/抖音推广引流平台
  • 长沙专业网站设计平台/中国品牌策划公司排名
  • 做网站要多少的分辨率/seo优化网络公司排名