O que pydicom faz?
Use pydicom para E/S de conjuntos de dados DICOM e processamento de pixels. A versão 3.0.2 é a
versão estável atual revisada aqui. Ela corrige CVE-2026-32711, um problema de path-traversal em DICOMDIR
criado de forma maliciosa. pydicom 3.0.2 declara Python >=3.10; seu
dicionário DICOM embutido é 2024c, enquanto o Padrão DICOM ativo pode ser mais recente.
Fronteira de segurança obrigatória
- Trabalhe apenas com dados locais que o usuário está autorizado a acessar.
- Metadados DICOM, nomes de arquivo, elementos privados, overlays, conteúdo estruturado e pixels podem conter informações protegidas de saúde (PHI).
- Nunca imprima
Dataset, exporte metadados/JSON completos ou registre valores de elementos por padrão. Use uma lista de permissões documentada e saída agregada. - pydicom é um framework DICOM geral, não um visualizador de diagnóstico. Saída de pixel, validação, conversão e disponibilidade de plugins não são alegações de diagnóstico.
- Desidentificação é específica de perfil, propósito, destinatário, jurisdição e contexto de ameaça. Requer verificação de especialista em privacidade/DICOM.
- Nunca afirme que um script de remoção de etiqueta é compliance com DICOM PS3.15, HIPAA, GDPR ou outro. Preserve originais e audite saídas derivadas.
- Trate chaves de pseudonimização determinísticas e mapas de UID como segredos de reidentificação: use privilégio mínimo e armazenamento de segredos criptografado/gerenciado, nunca cometa, sincronize, registre ou compartilhe-os com derivados, e defina backup, rotação, revogação e procedimentos de destruição. Uma chave vazada invalida a separação pretendida; a rotação também altera mapeamentos determinísticos.
- Defina limites explícitos de arquivo de entrada, contagem de arquivos, contagem de quadros, bytes decodificados e saída antes de analisar conjuntos de dados não confiáveis ou excepcionalmente grandes.
Instalação
Crie ou ative um ambiente isolado, então instale a versão exata revisada:
uv pip install "pydicom==3.0.2"
Arrays de pixels descomprimidos e renderização de imagem:
uv pip install "pydicom==3.0.2" "numpy==2.5.1" "Pillow==12.3.0"
Instale apenas os plugins de sintaxe de transferência necessários para a implantação:
# JPEG/JPEG-LS, JPEG 2000/HTJ2K e RLE mais rápido através de 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"
# Codificador/decodificador JPEG-LS
uv pip install "numpy==2.5.1" "pyjpegls==1.5.1"
# Decodificador alternativo com wheels específicos de plataforma
uv pip install "python-gdcm==3.2.6"
As licenças dos plugins e wheels diferem por pacote/plataforma; revise-os antes da implantação. Pillow tem limitações de decodificação documentadas e pydicom adverte que a saída do plugin deve ser verificada independentemente.
Os wheels de codec nativo ampliam a fronteira de segurança da cadeia de suprimentos e de memória. Para uma implantação controlada, resolva esses pins exatos em um host de build confiável, bloqueie e verifique hashes/procedência dos wheels, espelhe artefatos aprovados internamente, escaneie-os e instale com imposição de hash em vez de resolver do índice público em tempo de execução.
Escolha o workflow
- Precisa de uma visão geral agregada: execute
scripts/extract_metadata.py. - Precisa de verificações técnicas limitadas: execute
scripts/dicom_inventory.py. - Precisa de uma pré-verificação de implantação de codec: execute
scripts/transfer_syntax_inspector.py. - Precisa de planejamento de quadros/memória: execute
scripts/pixel_frame_planner.py. - Precisa de um quadro renderizado não diagnóstico: execute
scripts/dicom_to_image.py. - Precisa de um derivado pseudonimizado: leia a seção de desidentificação, crie
um perfil de ação revisado localmente, então execute
scripts/anonymize_dicom.pyescripts/deidentification_audit.py. - Precisa verificar um mapa de UID sensível: execute
scripts/uid_mapping_validator.py.
Ler conjuntos de dados com segurança
dcmread() retorna um FileDataset, uma subclasse de Dataset com estado de Formato de Arquivo
como file_meta, preâmbulo e codificação original.
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"),
}
Use:
stop_before_pixels=Truepara trabalho somente com metadados.specific_tags=[...]para uma lista de permissões mínima.defer_size="1 MiB"quando uma gravação posterior precisar preservar valores grandes.force=False(padrão).force=Trueapenas ignora a verificação de cabeçalho de Formato de Arquivo; não prova que os bytes são DICOM válido.
Não chame print(ds), repr(ds) ou itere valores em logs em dados clínicos.
Dataset, DataElement e sequências
Acesse elementos padrão por palavra-chave e verifique a ausência:
modality = ds.get("Modality", "UNSPECIFIED")
if "ReferencedImageSequence" in ds:
for item in ds.ReferencedImageSequence:
referenced_class = item.get("ReferencedSOPClassUID")
Acesso por tag, como ds[0x0010, 0x0010], retorna um DataElement; seu .value
é separado. Sequence se comporta como uma lista de itens Dataset aninhados. Ações de
privacidade devem percorrer recursivamente cada item da sequência, não apenas o nível superior.
Ao criar um arquivo, use FileMetaDataset para o grupo 0002, mantenha os UIDs do dataset e file-meta
SOP consistentes, defina um UID de Sintaxe de Transferência e escreva em Formato de Arquivo
forçado:
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
# Adicione todos os atributos exigidos pelo IOD selecionado antes de escrever.
dcmwrite("new.dcm", ds, enforce_file_format=True, overwrite=False)
write_like_original está obsoleto no pydicom 3.0; use
enforce_file_format. Uma gravação bem-sucedida não é conformidade completa com IOD PS3.3.
UIDs e sintaxe de transferência
O UID de Sintaxe de Transferência de Informação de Metadados de Arquivo controla a codificação do dataset e compressão de pixels:
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 escolhe a codificação de gravação a partir do UID de Sintaxe de Transferência antes de flags legadas do dataset. Não substitua UIDs estruturais (Sintaxe de Transferência, Classe SOP, ou UIDs de esquema de codificação) durante a pseudonimização. A substituição de UID de instância/referência deve ser um-para-um e consistente em todo o escopo declarado.
Leia references/transfer_syntaxes.md antes de compressão, descompressão ou encapsulamento.
Dados de pixel e quadros
A API estável pydicom.pixels suporta decodificação baseada em caminho e específica de quadro:
from pydicom.pixels import pixel_array
# Lê apenas o quadro selecionado onde a origem permite.
frame = pixel_array("authorized/image.dcm", index=0, raw=False)
Semântica de forma:
- quadro único em tons de cinza:
(rows, columns) - multi-quadro em tons de cinza:
(frames, rows, columns) - quadro único colorido:
(rows, columns, samples) - multi-quadro colorido:
(frames, rows, columns, samples)
raw=False converte dados de pixel YCbCr para RGB quando possível; raw=True retém
o espaço de cor decodificado após processamento mínimo obrigatório. Use
iter_pixels(path, indices=[...]) para iteração limitada de multi-quadros.
Para exibição em tons de cinza, aplique transformações nesta ordem:
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/rescale e VOI/windowing alteram a semântica de exibição/valor.
MONOCHROME1 pode exigir inversão de apresentação. Palette Color requer
apply_color_lut(). Estados de apresentação e comportamento ICC podem exigir um
visualizador validado. Nunca use normalização min/max por quadro para análise quantitativa.
Compressão, descompressão e encapsulamento
- Acessar
pixel_arraydecodifica conforme necessário, mas não altera o dataset. Dataset.decompress()altera Pixel Data no lugar, define Explicit VR Little Endian, atualiza metadados de imagem e gera um novo SOP Instance UID por padrão.Dataset.compress(uid)altera Pixel Data e Syntax Transfer no lugar e gera um novo SOP Instance UID por padrão.- Codificadores internos/encontrados do pydicom 3.0 cobrem RLE Lossless, JPEG-LS e JPEG 2000 combinações documentadas na matriz de plugins estável.
- Cada quadro comprimido é codificado separadamente e então encapsulado. Use
encapsulate()ouencapsulate_extended()para quadros codificados externamente. - Leia quadros com
pydicom.encaps.generate_frames()ouget_frame()atuais; nomes de geradores de encapsulamento legados estão obsoletos para pydicom 4.
Sempre inspecione as capacidades primeiro, limite bytes/quadros decodificados e verifique a correção do pixel independentemente. A aceitabilidade da compressão com perdas está fora do pydicom e da especificação de codificação DICOM.
JSON DICOM e elementos privados
Dataset.to_json(), to_json_dict() e Dataset.from_json() implementam o
Modelo JSON DICOM, mas pydicom documenta o suporte a JSON como beta. JSON completo pode
incorporar dados binários e expor cada identificador e payload de pixel. Não o emita
como um relatório de metadados. Um manipulador BulkDataURI introduz armazenamento separado,
autorização e obrigações de recuperação.
Elementos privados não são padronizados e podem conter PHI:
# Remoção recursiva, mas não desidentificação suficiente por si só.
ds.remove_private_tags()
Retenha elementos privados apenas sob uma política explícita de privado-seguro revisada. Leia references/common_tags.md para acesso a tags, classes de privacidade e ponteiros padrão.
Workflow de desidentificação
DICOM PS3.15 Anexo E afirma explicitamente que perfis de confidencialidade não garantem remoção de todas as informações de identificação e não substituem um processo completo de desidentificação.
- Defina propósito, destinatários, necessidades de vinculação, regulamentações, modelo de ameaça e risco de reidentificação aceitável.
- Selecione o Perfil de Confidencialidade de Nível de Aplicação Básico e opções necessárias (pixel, características visuais reconhecíveis, gráficos, conteúdo estruturado, descritores, informações temporais, características do paciente, dispositivos, instituições, UIDs e dados privados seguros).
- Preserve objetos de origem inalterados em armazenamento controlado.
- Aplique cada ação recursivamente, incluindo sequências aninhadas.
- Substitua UIDs de instância/referência consistentemente em todo o escopo; preserve UIDs estruturais.
- Decida o tratamento de data/hora explicitamente. Um deslocamento fixo pode preservar intervalos, mas datas parciais, fusos horários, horas isoladas, dias bissextos, vinculação longitudinal e eventos externos exigem política revisada.
- Inspecione pixels, overlays, gráficos, conteúdo estruturado e características visuais
reconhecíveis. Não infira pixels limpos de metadados ausentes ou defina
BurnedInAnnotation=NOsem verificação. - Reconstrua Informações de Metadados de Arquivo e preâmbulo para evitar vazamento.
- Execute validação técnica e uma auditoria de desidentificação, então realize verificação especializada e revisão de risco documentada.
O script incluído intencionalmente define PatientIdentityRemoved como NO porque
ele não pode estabelecer desidentificação bem-sucedida.
CLIs auxiliares
Todos os caminhos --help são livres de dependências. As ferramentas não realizam acesso à rede e
emitem nenhum valor DICOM além de listas de permissões técnicas estreitas.
O conteúdo incluído consiste nas duas referências vinculadas, os scripts auxiliares documentados e testes sintéticos. A dependência de tempo de execução do pydicom é instalada a partir do lançamento fixado do PyPI.
# Metadados agregados redigidos
python scripts/extract_metadata.py authorized/ --recursive
# Inventário técnico apenas de metadados
python scripts/dicom_inventory.py authorized/ --recursive
# Capacidades de codec/plugin instalados
python scripts/transfer_syntax_inspector.py --input authorized/image.dcm
# Plano de forma, bytes e transformação de quadro
python scripts/pixel_frame_planner.py authorized/image.dcm --frames 0,2-4
# Um quadro não diagnóstico
python scripts/dicom_to_image.py authorized/image.dcm frame.png \
--acknowledge-pixel-phi
# Crie uma chave secreta, depois um derivado pseudonimizado com escopo mais auditoria
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
# Auditar metadados candidatos; sem descompressão de pixel
python scripts/deidentification_audit.py derived/out.dcm
# Validar um mapeamento de UID sensível explicitamente solicitado
python scripts/uid_mapping_validator.py derived/uid-map.json \
--uid-key-file project.key --uid-scope export-v1
O arquivo de chave bruta gerado é uma conveniência local controlada e é criado com permissões apenas do proprietário. Para produção, materialize bytes de chave de um gerenciador de segredos aprovado em um arquivo efêmero bloqueado, restrinja o acesso ao serviço de desidentificação e remova-o com segurança depois. Armazene qualquer mapa de UID opcional separadamente dos derivados; ele vincula diretamente identificadores originais e de substituição.
Notas de migração do pydicom 3.0
read_file()ewrite_file()foram removidos; usedcmread()edcmwrite().write_like_originalestá obsoleto; useenforce_file_format.pydicom.pixel_data_handlersestá obsoleto para remoção no v4; usepydicom.pixels.Dataset.pixel_arrayusa o novo backend de pixels por padrão e converte YCbCr para RGB quando possível.JPEGLosslessagora significa UID1.2.840.10008.1.2.4.57;JPEGLosslessSV1é.70.Dataset.is_little_endianeis_implicit_VRestão obsoletos para v4.
Fontes (verificadas em 2026-07-23)
- pydicom 3.0.2 no PyPI — lançado 2026-06-25, inclui CVE-2026-32711 corrigido.
- pydicom.readthedocs.io — documentação oficial.
- Código fonte no GitHub — licenciado sob MIT.
- PS3.3, PS3.5 e PS3.15 — Padrão DICOM.