mcpField
D
dicom-processing

dicom-processing

github.com/awslabs数据与数据库6883 次安装4 周前更新
代码仓库

关于 dicom-processing

面向处理 DICOM 和 NIfTI 医学影像的流程技能,提供转换、读取与去标识化指导。涵盖批量按序列处理及 BIDS 目录组织。

主要功能

  1. 01DICOM 转 NIfTI 并生成 BIDS 侧车文件
  2. 02读取 DICOM 头信息与像素数据
  3. 03移除 PHI 并处理私有标签
  4. 04检查 NIfTI 体积与仿射矩阵
  5. 05按 SeriesInstanceUID 批量处理

适用场景

  1. 01将 DICOM 序列转换为压缩 NIfTI
  2. 02检查医学影像的头信息和像素
  3. 03对单个或大型队列进行去标识化
  4. 04按 BIDS 规范整理影像数据集

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/awslabs/hcls-agent-skills --skill dicom-processing

安装后在 Claude Code 中输入/dicom-processing确认已加载。

详细介绍

DICOM 处理

概述

用于转换、读取和去标识化 DICOM 与 NIfTI 格式医学图像的流水线技能。提供确定性的命令和代码,用于:

  • 使用 dcm2niix 将 DICOM 转换为 NIfTI(包括 BIDS 辅助文件)
  • 使用 pydicom 读取 DICOM 头信息和像素数据
  • 使用 pydicom 或 CTP DicomAnonymizer 移除 PHI(去标识化)
  • 使用 nibabel 检查 NIfTI
  • 按 SeriesInstanceUID 分组进行批处理
  • 按 BIDS 规范组织目录

当用户处理 .dcm、.nii、.nii.gz、DICOM 目录或匿名化工作流时,请使用此技能。

用法

1. 将 DICOM 序列转换为 NIfTI(dcm2niix)
# Standard conversion: gzip output, BIDS sidecar, pattern-named files
dcm2niix -z y -b y -f %p_%s -o output_dir input_dir

标志(请记住):

标志含义
-z y输出 gzip 文件(.nii.gz)
-b y生成 BIDS JSON 辅助文件
-f %p_%s文件名模式:%p = 协议,%s = 序列号
-m n不要合并跨序列的 2D 切片(防止不同序列混合)
-o输出目录

常见命名标记:%p 协议,%s 序列,%t 时间,%i 患者 ID,%n 患者姓名,%d 描述。

2. 使用 pydicom 读取 DICOM 文件
import pydicom

ds = pydicom.dcmread('file.dcm')
print(ds.PatientName, ds.StudyDate, ds.Modality)
print(ds.pixel_array.shape)  # numpy array of pixel data
3. 使用 pydicom 对 DICOM 文件进行去标识化
import pydicom
from pydicom.uid import generate_uid

ds = pydicom.dcmread('file.dcm')

tags_to_remove = [
    'PatientName', 'PatientID', 'PatientBirthDate',
    'InstitutionName', 'ReferringPhysicianName', 'StudyDate',
]
for tag in tags_to_remove:
    if tag in ds:
        del ds[tag]

ds.PatientID = 'ANON_001'

# Remove private (vendor) tags — they frequently contain PHI
ds.remove_private_tags()

# Replace UIDs so the study/series/instance cannot be linked back
ds.StudyInstanceUID  = generate_uid()
ds.SeriesInstanceUID = generate_uid()
ds.SOPInstanceUID    = generate_uid()

ds.save_as('anon.dcm')
4. 使用 CTP DicomAnonymizer 批量去标识化
# RSNA CTP / DicomBrowser DAP (DICOM Anonymizer Program)
java -jar DAP.jar -p profile.script -i input/ -o output/

适用于大型队列,或需要经过验证的 DICOM Supplement 142 配置文件的情况。

5. 使用 nibabel 加载 NIfTI 体数据
import nibabel as nib

img = nib.load('file.nii.gz')
data   = img.get_fdata()  # numpy ndarray
affine = img.affine       # 4x4 voxel-to-world transform
header = img.header
6. 批处理模式:按 SeriesInstanceUID 分组,逐序列转换
from pathlib import Path
from collections import defaultdict
import pydicom, subprocess

def group_by_series(input_dir):
    series = defaultdict(list)
    for p in Path(input_dir).rglob('*.dcm'):
        ds = pydicom.dcmread(p, stop_before_pixels=True)
        series[ds.SeriesInstanceUID].append(p)
    return series

def convert_all(input_dir, output_dir):
    Path(output_dir).mkdir(parents=True, exist_ok=True)
    # dcm2niix handles series grouping internally when given a directory
    subprocess.run(
        ['dcm2niix', '-z', 'y', '-b', 'y', '-f', '%p_%s',
         '-o', output_dir, input_dir],
        check=True,
    )
7. BIDS 目录组织
dataset/
├── dataset_description.json
├── participants.tsv
└── sub-01/
    └── ses-01/
        ├── anat/  sub-01_ses-01_T1w.nii.gz
        ├── func/  sub-01_ses-01_task-rest_bold.nii.gz
        └── dwi/   sub-01_ses-01_dwi.nii.gz

规则:sub-<label>/ses-<label>/<modality>/<sub>_<ses>_<suffix>.nii.gz,并配有匹配的 .json 辅助文件。

响应格式

  • 先给出用户需要的命令或代码,再进行解释
  • 结构为:确认输入 → 可运行的代码 → 说明关键参数 → 注意事项
  • 每项任务提供一个完整可运行的示例;不要列出所有替代方案
  • 代码注释应精简且实用(说明作用,而非存在原因)
  • 目标:50–100 行代码,并附简短说明

核心概念

格式与去标识化决策树
What is the target format?
├─ NIfTI (analysis) → dcm2niix -z y -b y
│  ├─ Need BIDS layout? → add -f sub-%i_ses-%t_%p, reorganize post-hoc
│  └─ Single series only? → point dcm2niix at series directory directly
└─ DICOM (archive/PACS) → pydicom read/write

De-identification method:
├─ Small cohort (< 100 studies) → pydicom script (remove tags + private + replace UIDs)
├─ Large cohort or regulatory → CTP DicomAnonymizer with Supplement 142 profile
└─ Burned-in pixel PHI risk?
   ├─ US / Secondary Capture / Screenshots → YES: add OCR + pixel masking step
   └─ CT / MR / PT → Usually NO: tag-level de-ID sufficient

DICOM 层级。 Patient → Study → Series → Instance。“序列”是转换的基本单位——一个 NIfTI 体数据通常对应一个 SeriesInstanceUID。

UID 是标识符,不是机密信息,但可以用于关联。 两个文件若具有相同的 StudyInstanceUID,则来自同一次检查。去标识化必须替换 UID(generate_uid()),以断开不同发布版本之间的关联。

私有标签可能包含 PHI。 特定厂商的标签(奇数群组号)通常会嵌入操作员备注、患者 ID 或烧录的元数据。务必调用 ds.remove_private_tags()。

像素数据也可能包含 PHI。 超声影像、二次捕获图像和屏幕截图中经常会在像素内烧录患者姓名/MRN。移除标签并不会清除像素——存在此类风险时,应另外运行 OCR 并进行遮罩处理。

几何和模态相关的重要 DICOM 标签:

标签名称用途
(0008,0060)ModalityCT / MR / CR / US / PT ...
(0018,0050)SliceThicknessmm
(0028,0030)PixelSpacing面内间距 [row, col] mm
(0020,0032)ImagePositionPatient切片在患者坐标系中的原点
(0020,0037)ImageOrientationPatient行/列方向余弦

这五个标签足以重建 NIfTI affine 矩阵。

NIfTI 与 DICOM。 NIfTI 将一个 3D/4D 体数据及其单个 affine 矩阵存储在一起;DICOM 则存储切片级元数据。转换器(dcm2niix)会汇总一个序列中的切片,并根据上述标签计算 affine 矩阵。

快速参考

# Convert
dcm2niix -z y -b y -f %p_%s -o out/ in/

# Skip merging across series (safer)
dcm2niix -z y -b y -m n -f %p_%s -o out/ in/

# Batch anonymization (CTP)
java -jar DAP.jar -p profile.script -i input/ -o output/
# Read DICOM
ds = pydicom.dcmread('file.dcm')
ds.PatientName, ds.Modality, ds.pixel_array.shape

# Header-only (fast, no pixels)
ds = pydicom.dcmread('file.dcm', stop_before_pixels=True)

# Anonymize core fields
for t in ['PatientName','PatientID','PatientBirthDate',
          'InstitutionName','ReferringPhysicianName','StudyDate']:
    if t in ds: del ds[t]
ds.remove_private_tags()
ds.StudyInstanceUID  = generate_uid()
ds.SeriesInstanceUID = generate_uid()
ds.SOPInstanceUID    = generate_uid()

# Load NIfTI
img = nib.load('file.nii.gz'); data = img.get_fdata(); aff = img.affine

常见错误

  • 错误: DICOM 去标识化时未移除私有标签 正确做法: 始终在去标识化流程中调用 ds.remove_private_tags() 原因: 厂商私有标签(奇数群组号)通常包含 PHI,标准的标签级清理无法将其移除

  • 错误: 匿名化后保留原始 UID 正确做法: 对每个去标识化文件,使用 generate_uid() 替换 StudyInstanceUID、SeriesInstanceUID 和 SOPInstanceUID 原因: 原始 UID 可关联回源 PACS——两个文件共享同一个 StudyInstanceUID,就能看出它们来自同一次检查

  • 错误: 使用 dcm2niix 默认的合并行为而不进行验证 正确做法: 使用 -m n 禁用合并,或根据预期序列列表检查输出文件数量 原因: 默认合并可能会将不同的采集数据合并到一个 NIfTI 体积中,导致数据损坏

  • 错误: 去标识化时忽略像素数据中烧录的注释 正确做法: 对超声、二次捕获和截图模态,添加 OCR 检测和像素遮罩步骤 原因: 标签级去标识化不会清理像素——标签移除后,烧录在图像中的患者姓名/MRN 仍然存在

  • 错误: 从 dcm2niix 输出未压缩的 .nii 文件 正确做法: 始终向 dcm2niix 传递 -z y,以输出经过 gzip 压缩的 .nii.gz 文件,除非下游工具明确要求未压缩文件 原因: 未压缩的 NIfTI 文件体积大 3–5 倍,会浪费存储空间并减慢传输速度,对大多数流程却没有任何好处

  • 错误: 只需要 DICOM 头信息时仍读取完整像素数据 正确做法: 对于仅需元数据的扫描,使用 pydicom.dcmread(path, stop_before_pixels=True) 原因: 对大型队列加载像素数组会浪费内存和时间,而实际上只需要 Modality、SeriesInstanceUID 或 SliceThickness 等标签

  • 错误: 将 DICOMDIR 当作文件目录并遍历其中的条目 正确做法: 改用 Path(input_dir).rglob('*.dcm') 遍历实际的 .dcm 文件 原因: DICOMDIR 是具有自身结构的索引文件,可能不完整、已过期或不存在;直接遍历文件更可靠

参考资料

评论

支持 Markdown