欢迎光临
我们一直在努力

DICOM入门系列——Python解析DICOM文件:pydicom实战指南

在前两篇文章中,我们了解了DICOM作为医学影像“通用语言”的核心价值,以及DICOM文件的底层结构(从文件元信息头到标签驱动的数据集)。但理论知识的最终落脚点是实践——如何用代码直接读取DICOM文件中的患者信息、检查参数,甚至提取图像像素数据?

Python作为医学影像处理领域的主流编程语言之一,拥有强大的第三方库支持。其中,pydicom​ 是最受欢迎、最易上手的DICOM文件解析工具,它能够轻松读取、修改和保存DICOM文件,并提供了直观的API访问每一个数据元素(Tag)。

本文将通过完整的代码示例与逐步解析,带你用pydicom实现以下目标:

  • 安装与配置pydicom环境;

  • 读取DICOM文件的基础信息(如患者姓名、检查日期);

  • 提取图像像素数据并可视化;

  • 修改DICOM元数据并保存新文件;

  • 常见问题与实用技巧。

  • 无论你是医学生、影像科工程师,还是想用Python处理医学数据的开发者,这篇文章都能帮你快速上手DICOM文件的实战操作!


    一、准备工作:安装pydicom与环境配置

    1. 安装pydicom

    pydicom是一个纯Python实现的库(无需依赖C/C++底层库),安装非常简单,只需通过pip执行以下命令:

    pip install pydicom

    📌 推荐使用Python 3.7及以上版本。如果需要处理图像显示(如绘制像素矩阵),可额外安装matplotlib:

    pip install matplotlib

    2. 准备DICOM文件

    你可以从以下途径获取测试用的DICOM文件(建议选择小型的CT或X光片文件,文件体积小且内容清晰):

    • 公开数据集:如The Cancer Imaging Archive (TCIA)、DICOM Library(提供免费下载);

    • 医院/实验室:联系影像科获取脱敏后的示例文件;

    • 自备设备:通过CT/MRI设备导出单个患者的DICOM文件(通常为.dcm格式)。

    将文件保存到本地目录(例如命名为example.dcm),后续代码将以该文件为例。


    二、读取DICOM文件的基础信息(标签解析实战)

    1. 加载DICOM文件

    使用pydicom的dcmread()函数可以直接读取.dcm文件,返回一个Dataset对象(即DICOM数据集,包含所有数据元素)。

    import pydicom

    # 读取DICOM文件
    dcm_file = "example.dcm" # 替换为你的文件路径
    ds = pydicom.dcmread(dcm_file)

    # 打印文件的基本信息(所有数据元素的摘要)
    print(ds)

    运行后会输出类似以下内容(简化版):

    (0008, 0016) SOP Class UID UI: CT Image Storage
    (0008, 0018) SOP Instance UID UI: 1.2.840.113619.2.55.3.2831164382.145.1643824682.81
    (0010, 0010) Patient's Name PN: '张三^三'
    (0010, 0020) Patient ID LO: '123456'
    (0010, 0030) Patient's Birth Date DA: '19800101'
    (0010, 0040) Patient's Sex CS: 'M'
    (0008, 0060) Modality CS: 'CT'
    (0028, 0010) Rows US: 512
    (0028, 0011) Columns US: 512
    (0028, 0100) Bits Allocated US: 16
    (7FE0, 0010) Pixel Data OW: (Array of 512x512x2 bytes)

    每一行代表一个数据元素(Tag),格式为(Group,Element) VR: 值(例如(0010,0010)是患者姓名,VR为PN(人名),值是“张三^三”)。


    2. 按Tag精确提取关键信息

    如果只想获取特定信息(如患者姓名、检查日期),可以直接通过Tag访问对应的值。pydicom将常用的Tag定义为常量(如PatientName、StudyDate),使用起来更直观。

    # 提取患者姓名(Tag: (0010,0010))
    patient_name = ds.PatientName
    print("患者姓名:", patient_name) # 输出: 张三^三

    # 提取患者ID(Tag: (0010,0020))
    patient_id = ds.PatientID
    print("患者ID:", patient_id) # 输出: 123456

    # 提取出生日期(Tag: (0010,0030))
    birth_date = ds.PatientBirthDate
    print("出生日期:", birth_date) # 输出: 19800101(格式为YYYYMMDD)

    # 提取性别(Tag: (0010,0040))
    gender = ds.PatientSex
    print("性别:", gender) # 输出: M(男)或 F(女)

    # 提取检查模态(Tag: (0008,0060))
    modality = ds.Modality
    print("检查模态:", modality) # 输出: CT(CT扫描)、MR(MRI)、CR(X光)

    # 提取检查描述(Tag: (0008,1030))
    study_description = ds.StudyDescription # 如果存在
    print("检查描述:", study_description or "无描述")

    📌 注意:

    • 如果某个Tag不存在(例如文件中没有检查描述),直接访问ds.StudyDescription会报错。安全的方式是先检查是否存在:

      if 'StudyDescription' in ds:
      print("检查描述:", ds.StudyDescription)
      else:
      print("无检查描述")

    • 患者姓名(PatientName)的类型是pydicom.valuerep.PersonName,若需拆分为姓和名,可通过family_name和given_name属性获取:

      print("姓:", patient_name.family_name) # 张三
      print("名:", patient_name.given_name) # 三


    三、提取图像像素数据并可视化(从二进制到图像)

    DICOM文件的核心价值之一是包含医学图像的原始像素数据(存储在Tag (7FE0,0010)中)。通过pydicom,我们可以轻松提取这些数据,并用matplotlib绘制为可视化的灰度图像。

    1. 获取像素数据

    像素数据存储在ds.pixel_array属性中,它是一个NumPy数组,形状为(行数, 列数)(例如512×512)。

    import matplotlib.pyplot as plt

    # 检查是否存在像素数据(通常CT/MRI文件都有)
    if hasattr(ds, 'pixel_array'):
    pixel_data = ds.pixel_array # 获取NumPy数组
    print("图像尺寸(行, 列):", pixel_data.shape) # 例如 (512, 512)
    print("像素值范围:", pixel_data.min(), "~", pixel_data.max()) # 例如 0 ~ 255(8bit)或 0 ~ 4095(12bit)

    # 可视化单幅图像(适用于CT/MRI的单一切片)
    plt.imshow(pixel_data, cmap='gray') # 使用灰度色阶
    plt.title(f"DICOM图像预览 (患者: {ds.PatientName}, 模态: {ds.Modality})")
    plt.axis('off') # 隐藏坐标轴
    plt.show()
    else:
    print("该DICOM文件不包含图像像素数据(可能是报告或其他类型文件)")

    📌 关键说明:

    • pixel_array的数值范围取决于图像的比特深度(如16bit图像的值可能是0~65535,8bit是0~255)。

    • CT图像通常是16bit,像素值对应的是Hounsfield单位(HU),需要通过窗宽窗位(Window Width/Level)调整显示效果(后续进阶文章会讲解)。

    • 如果是多帧图像(如动态超声),pixel_array可能是三维数组(帧数×行×列),需额外处理。


    2. 多切片图像的批量预览(可选)

    如果DICOM文件是多切片序列(如CT扫描的连续断层),通常一个文件夹下会有多个.dcm文件(每个文件对应一个切片)。此时可以遍历文件夹,批量读取并显示所有图像:

    import os

    folder_path = "dicom_series_folder" # 替换为存放多个DICOM文件的文件夹路径
    dcm_files = [f for f in os.listdir(folder_path) if f.endswith('.dcm')]
    dcm_files.sort() # 按文件名排序(确保切片顺序正确)

    for i, filename in enumerate(dcm_files[:5]): # 只显示前5张切片(避免过多)
    filepath = os.path.join(folder_path, filename)
    ds_slice = pydicom.dcmread(filepath)
    plt.subplot(1, 5, i+1) # 1行5列的子图
    plt.imshow(ds_slice.pixel_array, cmap='gray')
    plt.title(f"Slice {i+1}")
    plt.axis('off')
    plt.suptitle(f"DICOM切片序列预览 (共{len(dcm_files)}张)", y=1.05)
    plt.show()


    四、修改DICOM元数据并保存新文件

    pydicom不仅支持读取,还允许修改DICOM文件中的元数据(如患者姓名、检查日期),并保存为新的.dcm文件。

    1. 修改元数据

    直接通过Tag赋值即可修改(例如将患者姓名改为“李四^四”):

    # 修改患者姓名(注意:PatientName是PersonName类型,需用正确格式)
    new_name = pydicom.valuerep.PersonName("李四^四")
    ds.PatientName = new_name

    # 修改检查日期(Tag: (0008,0020) Study Date,格式为YYYYMMDD)
    ds.StudyDate = '20250101'

    # 修改备注信息(Tag: (0010,4000) Patient Comments)
    ds.add_new((0010, 4000), 'LT', '这是通过pydicom修改的测试文件') # LT表示长文本

    📌 注意:

    • 修改Tag时需确保其VR(值类型)正确。例如日期(StudyDate)必须是字符串格式(如'20250101'),不能是数字。

    • 如果要添加新的Tag(原文件不存在),使用add_new(Tag, VR, value)方法(如上面的Patient Comments)。


    2. 保存修改后的文件

    使用save_as()方法将修改后的Dataset保存为新的.dcm文件:

    output_path = "modified_example.dcm"
    ds.save_as(output_path)
    print(f"修改后的DICOM文件已保存至: {output_path}")

    打开新文件后,通过DICOM查看器(如MicroDicom)或pydicom再次读取,即可验证修改是否生效。


    五、常见问题与实用技巧

    1. 文件打不开或报错?​

    • 确保文件是标准的DICOM格式(后缀为.dcm,且包含“DICM”标识)。

    • 如果文件是私有的非标准格式,pydicom可能无法解析全部数据,但通常能读取基础信息(如像素数据)。

    2. 如何知道一个Tag的具体含义?​

    • 查阅DICOM标准文档(如Part 6:Data Dictionary),或使用在线工具(如DICOM Tag Browser)。

    • pydicom中可通过dir(ds)查看所有可访问的Tag名称(如PatientName、Modality)。

    3. 像素数据是8bit还是16bit?如何调整显示亮度?​

    • 通过ds.BitsAllocated查看比特深度(如16表示16bit,8表示8bit)。

    • 若像素值范围过大(如16bit的0~65535),可通过归一化显示:

      pixel_data_normalized = (pixel_data – pixel_data.min()) / (pixel_data.max() – pixel_data.min()) * 255
      plt.imshow(pixel_data_normalized.astype('uint8'), cmap='gray')

    4. 如何批量处理一个文件夹下的所有DICOM文件?​

    结合os.listdir()遍历文件夹,对每个.dcm文件执行读取→解析→处理→保存操作(参考前面的多切片预览代码)。


    六、小结:pydicom——医学影像数据的“Python钥匙”

    通过本文,你已经掌握了用pydicom解析DICOM文件的核心技能:

    ✅ 读取基础信息(患者姓名、检查模态、设备参数);

    ✅ 提取图像像素数据并可视化(CT/MRI的灰度图像);

    ✅ 修改元数据并保存新文件(适用于数据脱敏或标注);

    ✅ 处理多切片序列(批量预览或分析)。

    pydicom的强大之处在于,它既适合快速提取DICOM中的关键信息(如科研中的患者统计),也能作为医学AI开发的“数据预处理工具”(将DICOM转换为模型可读的NumPy数组)。

    赞(0)
    未经允许不得转载:171主机测评 » DICOM入门系列——Python解析DICOM文件:pydicom实战指南
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址