如何使用pyDicom编辑DICOM序列中的嵌套/子TIME(VR=TM)标签
解决方案
核心思路
要覆盖DICOM序列内的嵌套标签,最优方案是递归遍历整个DICOM数据集的所有元素:遇到序列(VR为SQ)就进入序列的每一个子项递归处理,遇到符合要求的TM类型标签直接替换即可。
同时你原有代码存在重复读写文件的性能问题:每修改一个标签就读取、保存一次文件,我们会在优化方案里一并修正,改为单次读取、全量修改后单次保存。
优化后完整代码
import os import logging import pydicom TIME_TAGS = [ (0x10, 0x32), # 患者出生时间 (0x40, 0x245), # 执行步骤开始时间 (0x8, 0x13), # 实例创建时间 (0x8, 0x30), # 检查时间 (0x8, 0x31), # 序列时间 (0x8, 0x32), # 采集时间 (0x8, 0x33), # 内容时间 ] TIME_VAL_REPLACEMENT = '120000' def _process_dataset(ds: pydicom.Dataset) -> None: """递归处理单个DICOM数据集,替换所有符合要求的TM标签,包括嵌套序列内的标签""" for elem in ds.elements(): # 遇到序列则递归处理序列内的每一个子项 if elem.VR == 'SQ': for item in elem.value: _process_dataset(item) # 匹配到目标TM标签则替换值 elif elem.tag in TIME_TAGS and elem.VR == 'TM': logging.debug("Removing time (%s)", elem.tag) elem.value = TIME_VAL_REPLACEMENT def _clear_times(dir_name: str) -> None: ''' 将目录下所有DICOM文件的标准TIME标签(含嵌套序列内标签)设置为统一占位值 dir_name: 待处理目录的完整路径 ''' for dcm_file in os.listdir(dir_name): dcm_path = os.path.join(dir_name, dcm_file) # 跳过非文件、或者读取失败的无效DICOM if not os.path.isfile(dcm_path): continue try: dcmfile = pydicom.dcmread(dcm_path) except Exception as e: logging.warning("Skip invalid DICOM file %s: %s", dcm_path, str(e)) continue # 递归处理整个数据集 _process_dataset(dcmfile) # 处理完成后统一保存 dcmfile.save_as(dcm_path)
方案优势
- 自动覆盖所有嵌套层级的标签:不需要手动枚举所有可能的序列路径,无论序列嵌套多少层都能匹配到目标标签
- 性能提升明显:单个文件仅读写1次,相比原方案每个标签读写一次的逻辑,文件越多、标签越多、嵌套越深,性能优势越大
- 可维护性强:后续需要新增要替换的TM标签,仅需要在
TIME_TAGS列表中添加对应标签即可
内容的提问来源于stack exchange,提问作者moo
相关产品推荐
相关产品推荐

