mcpField
P
pydicom

pydicom

github.com/kalarislabs数据与数据库12772 次安装今天更新
代码仓库

关于 pydicom

pydicom 技能为使用 pydicom 读取、检查和处理 DICOM 数据提供指导,面向需要在 Python 中处理医学影像数据的开发者与研究人员。内容特别强调 PHI 防护、受控像素处理及经审核的去标识化流程。

主要功能

  1. 01读取 DICOM 数据集与元数据
  2. 02像素和多帧处理指导
  3. 03传输语法与编解码检查
  4. 04聚合元数据和技术清单 CLI
  5. 05去标识化审核流程指导

适用场景

  1. 01检查授权的本地 DICOM 文件
  2. 02规划多帧像素处理资源
  3. 03预检传输语法与编解码能力
  4. 04制作并审核去标识化衍生数据

安装

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

$npx skills add https://github.com/kalarislabs/research-agent-skills --skill pydicom

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
common_tags.md
transfer_syntaxes.md
scripts/
__init__.py
_common.py
anonymize_dicom.py
deidentification_audit.py
dicom_inventory.py
dicom_to_image.py
extract_metadata.py
pixel_frame_planner.py
transfer_syntax_inspector.py
uid_mapping_validator.py

详细介绍

pydicom

使用 pydicom 进行 DICOM 数据集 I/O 和像素处理。此处审阅的当前稳定版本为 3.0.2。该版本修复了 CVE-2026-32711,这是一个由精心构造的 DICOMDIR 引发的路径遍历问题。pydicom 3.0.2 声明要求 Python >=3.10;其内置 DICOM 字典版本为 2024c,而在线 DICOM 标准可能已有更新。

强制安全边界

  • 仅处理用户获准访问的本地数据。
  • DICOM 元数据、文件名、私有元素、覆盖层、结构化内容和像素都可能包含受保护的健康信息(PHI)。
  • 默认情况下,绝不打印 Dataset、导出完整元数据/JSON 或记录元素值。请使用有文档记录的允许列表,并输出汇总信息。
  • pydicom 是通用 DICOM 框架,并非诊断查看器。像素输出、验证、转换和插件可用性都不构成诊断结论。
  • 去标识化取决于具体配置文件、目的、接收方、司法管辖区和威胁环境,必须由隐私/DICOM 专家进行验证。
  • 绝不要声称标签移除脚本符合 DICOM PS3.15、HIPAA、GDPR 或其他合规要求。保留原件并审计衍生输出。
  • 将确定性假名化密钥和 UID 映射视为可重新识别身份的机密:遵循最小权限原则,并使用加密的/受管理的机密存储;绝不将其提交、同步、记录日志或与衍生数据共享,并制定备份、轮换、撤销和销毁流程。密钥泄露会使预期的隔离失效;轮换也会改变确定性映射。
  • 在解析不可信或异常大的数据集之前,设置明确的输入文件、文件数量、帧数、解码字节数和输出限制。

安装

创建或激活隔离环境,然后安装经过审阅的确切版本:

uv pip install "pydicom==3.0.2"

未压缩像素数组和图像渲染:

uv pip install "pydicom==3.0.2" "numpy==2.5.1" "Pillow==12.3.0"

仅安装部署所需的传输语法插件:

# JPEG/JPEG-LS, JPEG 2000/HTJ2K, and faster RLE through pylibjpeg
uv pip install "numpy==2.5.1" "pylibjpeg==2.1.0" \
  "pylibjpeg-libjpeg==2.4.0" "pylibjpeg-openjpeg==2.5.0" \
  "pylibjpeg-rle==2.2.0"

# JPEG-LS encoder/decoder
uv pip install "numpy==2.5.1" "pyjpegls==1.5.1"

# Alternative decoder with platform-specific wheels
uv pip install "python-gdcm==3.2.6"

不同软件包/平台的插件许可证和 wheel 各不相同;部署前请先审阅。Pillow 存在有文档记录的解码限制,且 pydicom 提醒必须独立检查插件输出。

原生编解码器 wheel 会扩大供应链和内存安全边界。对于受控部署,请在可信构建主机上解析这些确切的固定版本,锁定并验证 wheel 的哈希/来源,在内部镜像获准的构件,对其进行扫描,并通过哈希校验强制安装,而不是在运行时从公共索引解析。

选择工作流

  1. 需要汇总概览:运行 scripts/extract_metadata.py。
  2. 需要有限范围的技术检查:运行 scripts/dicom_inventory.py。
  3. 需要编解码器部署预检:运行 scripts/transfer_syntax_inspector.py。
  4. 需要规划帧数/内存:运行 scripts/pixel_frame_planner.py。
  5. 需要渲染一个非诊断用途的帧:运行 scripts/dicom_to_image.py。
  6. 需要假名化衍生数据:阅读去标识化部分,创建经站点审阅的操作配置文件,然后运行 scripts/anonymize_dicom.py 和 scripts/deidentification_audit.py。
  7. 需要检查敏感 UID 映射:运行 scripts/uid_mapping_validator.py。

安全读取数据集

dcmread() 会返回一个 FileDataset,它是 Dataset 的子类,包含 file_meta、前导码和原始编码等文件格式状态。

from pathlib import Path
import pydicom

path = Path("authorized/input.dcm")
ds = pydicom.dcmread(
    path,
    stop_before_pixels=True,
    specific_tags=[
        "SOPClassUID",
        "Modality",
        "Rows",
        "Columns",
        "NumberOfFrames",
    ],
)

technical = {
    "sop_class": ds.get("SOPClassUID"),
    "modality": ds.get("Modality"),
    "rows": ds.get("Rows"),
    "columns": ds.get("Columns"),
}

请使用:

  • 仅处理元数据时使用 stop_before_pixels=True。
  • 使用 specific_tags=[...] 指定最小允许列表。
  • 后续写入必须保留大值时使用 defer_size="1 MiB"。
  • 使用 force=False(默认值)。force=True 只会跳过文件格式标头检查,并不能证明字节内容是有效的 DICOM。

处理临床数据时,不要调用 print(ds)、repr(ds),也不要将遍历得到的值写入日志。

Dataset、DataElement 和序列

通过关键字访问标准元素并检查元素是否缺失:

modality = ds.get("Modality", "UNSPECIFIED")
if "ReferencedImageSequence" in ds:
    for item in ds.ReferencedImageSequence:
        referenced_class = item.get("ReferencedSOPClassUID")

通过标签访问(例如 ds[0x0010, 0x0010])会返回一个 DataElement;其 .value 是单独的值。Sequence 的行为类似于嵌套 Dataset 项组成的列表。隐私 处理必须递归遍历每个序列项,而不能只处理顶层。

创建文件时,请使用 FileMetaDataset 存放组 0002,确保数据集和 文件元信息中的 SOP UID 一致,设置 Transfer Syntax UID,并以强制 文件格式写入:

from pydicom import dcmwrite
from pydicom.dataset import FileDataset, FileMetaDataset
from pydicom.uid import CTImageStorage, ExplicitVRLittleEndian, generate_uid

meta = FileMetaDataset()
meta.MediaStorageSOPClassUID = CTImageStorage
meta.MediaStorageSOPInstanceUID = generate_uid()
meta.TransferSyntaxUID = ExplicitVRLittleEndian

ds = FileDataset(None, {}, file_meta=meta, preamble=b"\0" * 128)
ds.SOPClassUID = meta.MediaStorageSOPClassUID
ds.SOPInstanceUID = meta.MediaStorageSOPInstanceUID
# Add all attributes required by the selected IOD before writing.
dcmwrite("new.dcm", ds, enforce_file_format=True, overwrite=False)

write_like_original 已在 pydicom 3.0 中弃用;请使用 enforce_file_format。写入成功并不代表符合完整的 PS3.3 IOD。

UID 和传输语法

文件元信息中的 Transfer Syntax UID 控制数据集编码和 像素压缩:

ts = ds.file_meta.TransferSyntaxUID
summary = {
    "uid": str(ts),
    "name": ts.name,
    "compressed": ts.is_compressed,
    "implicit_vr": ts.is_implicit_VR,
    "little_endian": ts.is_little_endian,
}

在 pydicom 3.0 中,写入编码会优先根据 Transfer Syntax UID 选择,然后才考虑旧版 数据集标志。伪名化时不要替换结构性 UID(Transfer Syntax、SOP Class 或 编码方案 UID)。实例/引用 UID 的替换必须一一对应,并在完整的声明范围内保持一致。

在压缩、解压缩或封装前,请阅读 references/transfer_syntaxes.md。

像素数据和帧

稳定的 pydicom.pixels API 支持基于路径、指定帧的解码:

from pydicom.pixels import pixel_array

# Reads only the selected frame where the source permits it.
frame = pixel_array("authorized/image.dcm", index=0, raw=False)

形状语义:

  • 单帧灰度:(rows, columns)
  • 多帧灰度:(frames, rows, columns)
  • 单帧彩色:(rows, columns, samples)
  • 多帧彩色:(frames, rows, columns, samples)

raw=False 会在可能的情况下将 YCbCr 像素数据转换为 RGB;raw=True 会保留 强制最小处理后的解码色彩空间。对于有界多帧迭代,请使用 iter_pixels(path, indices=[...])。

对于灰度显示,请按以下顺序应用变换:

from pydicom.pixels import apply_modality_lut, apply_voi_lut

modality_values = apply_modality_lut(frame, ds)
display_values = apply_voi_lut(modality_values, ds, index=0)

Modality LUT/重缩放和 VOI/窗宽窗位会改变显示和值的语义。 MONOCHROME1 可能需要反转显示。Palette Color 需要使用 apply_color_lut()。呈现状态和 ICC 行为可能需要经过验证的查看器。 定量分析中切勿使用逐帧最小值/最大值归一化。

压缩、解压缩和封装

  • 访问 pixel_array 会按需解码,但不会更改数据集。
  • Dataset.decompress() 会原地更改 Pixel Data,设置为 Explicit VR Little Endian,更新图像元数据,并默认生成新的 SOP Instance UID。
  • Dataset.compress(uid) 会原地更改 Pixel Data 和 Transfer Syntax,并 默认生成新的 SOP Instance UID。
  • pydicom 3.0 内置/可发现的编码器支持稳定版插件矩阵中记录的 RLE Lossless、JPEG-LS 和 JPEG 2000 组合。
  • 每个压缩帧都会单独编码,然后进行封装。对于外部编码的帧,请使用 encapsulate() 或 encapsulate_extended()。
  • 使用当前的 pydicom.encaps.generate_frames() 或 get_frame() 读取帧; 旧版封装生成器名称已在 pydicom 4 中弃用。

务必先检查功能支持情况,限制解码字节数/帧数,并独立验证像素正确性。有损压缩是否可接受不属于 pydicom 和 DICOM 编码规范的范畴。

DICOM JSON 和私有元素

Dataset.to_json()、to_json_dict() 和 Dataset.from_json() 实现了 DICOM JSON Model,但 pydicom 将 JSON 支持标记为 beta。完整 JSON 可能会内嵌 二进制数据,并暴露所有标识符和像素负载。不要将其作为元数据报告输出。BulkDataURI 处理器会带来额外的存储、授权和检索义务。

私有元素并未标准化,且可能包含 PHI:

# Recursive removal, but not sufficient de-identification by itself.
ds.remove_private_tags()

只有在明确审查过的安全私有元素策略下,才保留私有元素。 有关标签访问、隐私类别和标准参考,请阅读 references/common_tags.md。

去标识化工作流

DICOM PS3.15 附录 E 明确指出,保密配置文件无法保证移除所有身份识别信息,也不能替代完整的去标识化流程。

  1. 明确目的、接收方、关联需求、法规、威胁模型和可接受的重新识别风险。
  2. 选择基本应用级别保密配置文件以及所需选项(像素、可识别的视觉特征、图形、结构化内容、描述符、时间信息、患者特征、设备、机构、UID 和安全的私有数据)。
  3. 将源对象原样保存在受控存储中。
  4. 递归应用每项操作,包括嵌套序列。
  5. 在完整范围内一致地替换实例 UID/引用 UID;保留结构性 UID。
  6. 明确决定日期/时间的处理方式。固定偏移可以保留时间间隔,但不完整日期、时区、独立时间、闰日、纵向关联和外部事件都需要经过审核的策略。
  7. 检查像素、叠加层、图形、结构化内容和可识别的视觉特征。不能因缺少元数据就推断像素内容干净,也不能在未经验证的情况下将 BurnedInAnnotation=NO。
  8. 重建文件元信息和前导码,以防信息泄露。
  9. 执行技术验证和去标识化审计,然后进行专家验证和有记录的风险审查。

捆绑脚本会有意将 PatientIdentityRemoved 设为 NO,因为它无法确认去标识化已成功。

辅助 CLI

所有 --help 操作都不需要依赖项。这些工具不会访问网络,且除范围狭窄的技术白名单外,不会输出任何 DICOM 值。

捆绑内容包括两个链接的参考资料、有文档说明的辅助脚本和合成测试。pydicom 运行时依赖项从固定版本的 PyPI 发行版安装。

# Redacted aggregate metadata
python scripts/extract_metadata.py authorized/ --recursive

# Metadata-only technical inventory
python scripts/dicom_inventory.py authorized/ --recursive

# Installed codec/plugin capabilities
python scripts/transfer_syntax_inspector.py --input authorized/image.dcm

# Frame shape, byte, and transform plan
python scripts/pixel_frame_planner.py authorized/image.dcm --frames 0,2-4

# One non-diagnostic frame
python scripts/dicom_to_image.py authorized/image.dcm frame.png \
  --acknowledge-pixel-phi

# Create a secret key, then a scoped pseudonymized derivative plus audit
python scripts/anonymize_dicom.py --generate-uid-key project.key
python scripts/anonymize_dicom.py authorized/in.dcm derived/out.dcm \
  --uid-key-file project.key --uid-scope export-v1 \
  --audit-report derived/out.audit.json

# Audit candidate metadata; no pixel decompression
python scripts/deidentification_audit.py derived/out.dcm

# Validate an explicitly requested sensitive UID mapping
python scripts/uid_mapping_validator.py derived/uid-map.json \
  --uid-key-file project.key --uid-scope export-v1

生成的原始密钥文件仅为受控的本地便利措施,并且仅授予所有者权限。对于生产环境,请从经批准的密钥管理器中取出密钥字节并写入受限的临时文件,限制去标识化服务的访问权限,并在使用后安全删除。任何可选的 UID 映射都应与衍生文件分开存储;它会直接关联原始标识符和替换标识符。

pydicom 3.0 迁移说明

  • read_file() 和 write_file() 已移除;请使用 dcmread() 和 dcmwrite()。
  • write_like_original 已弃用;请使用 enforce_file_format。
  • pydicom.pixel_data_handlers 已弃用,并计划在 v4 中移除;请使用 pydicom.pixels。
  • 默认情况下,Dataset.pixel_array 使用新的像素后端,并会在可能时将 YCbCr 转换为 RGB。
  • JPEGLossless 现在表示 UID 1.2.840.10008.1.2.4.57; JPEGLosslessSV1 为 .70。
  • Dataset.is_little_endian 和 is_implicit_VR 已弃用,并计划在 v4 中移除。

来源(已于 2026-07-23 验证)

Agent 操作流程

  1. 检查环境。 确认数据访问权限、去标识化状态,以及适用的法规或规程。
  2. 明确输入。 根据数据或用户提供的信息确认格式、标识符和参数。任何会改变结果的值都应询问,不要猜测。
  3. 先运行小规模版本。 先使用去标识化样本或合成数据。
  4. 使用上述说明和参考资料执行完整任务。
  5. 验证结果。 根据临床指南和报告标准检查输出;临床内容须由具备资质的人员审核。
  6. 报告。 说明运行了什么(版本、命令、参数)、检查了什么,以及仍有哪些不确定之处。
如果发生以下情况请执行以下操作
数据似乎包含可识别患者身份的信息停止处理,并在继续处理前询问用户。
这些说明中的函数、标志或端点在已安装版本中不存在查看已安装版本自己的文档(help()、--help、官方文档),进行调整并告知用户。切勿虚构 API。
必需的输入、标识符或参数含义不明确询问用户,或在运行前明确说明所采用的假设。

诚信规则

  • 切勿捏造结果、参数、标识符、引文或统计数据。如果无法运行或验证某项内容,请直言说明。
  • 输出用于支持具备资质的专业人员作出决策,不构成医疗建议;切勿将其作为诊断或医嘱呈现。
  • 此处与特定版本相关的详情可能已经过时:请根据已安装版本的官方文档进行确认。
  • 对于会产生费用、占用共享 GPU 或云配额、涉及个人或患者数据,或无法撤销的操作,须事先征求同意。

评论

支持 Markdown