如何修复 pydicom 的 dcmread() 序言错误?

How do I fix pydicom's dcmread() preamble error?

我在处理给定路径中确实存在的 DICOM 文件时遇到 dcmread() 问题。我不确定出了什么问题。这是我的代码:

import pydicom

f = "/exact/path/hi.dcm"
fn = get_testdata_file(f)
ds = pydicom.dcmread(fn)

ds.SOPClassUID = ds.MediaStorageSOPClassUID

我遇到以下错误:

Traceback (most recent call last):
  File "addfields.py", line 14, in <module>
    ds = pydicom.dcmread(fn)
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/pydicom/filereader.py", line 871, in dcmread
    force=force, specific_tags=specific_tags)
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/pydicom/filereader.py", line 668, in read_partial
    preamble = read_preamble(fileobj, force)
  File "/Users/user/opt/anaconda3/lib/python3.7/site-packages/pydicom/filereader.py", line 605, in read_preamble
    preamble = fp.read(128)
AttributeError: 'NoneType' object has no attribute 'read'

但我不确定为什么,因为“hi.dcm”是一个存在的文件(路径正确)并且里面有元数据。我不知道什么是序言以及它是否出现在我正在处理的图像中。

免责声明:我是 pydicom 的贡献者。

错误发生是因为 get_testdata_file returns None,然后用作文件名。错误消息本身有点误导 - 在这种情况下提高 FileNotFoundValueError 可能会更好(Update:它提高 TypeError在当前的 pydicom 中)。相反发生的是,首先读取的是前导码(DICOM 图像的标记,由 128 个零字节后跟 'DICM' 组成),并且在尝试读取它时它崩溃了,因为文件指针是None.

这里是 documentation for get_testdata_file:

Return an absolute path to the first matching dataset with filename name.

First searches the local pydicom data store, then any locally available external sources, and finally the files available in the pydicom/pydicom-data repository.

所以这是一个方便的功能,主要是查找pydicom测试数据文件。
如果你已经有文件路径,你可以直接使用它:

import pydicom

fn = "/exact/path/hi.dcm"
ds = pydicom.dcmread(fn)

至于序言,如果 DICOM 文件没有序言(旧 ACR-NEMA 格式),您可以使用 force=True 参数读取此类文件:

ds = pydicom.dcmread(fn, force=True)

虽然我只会在你真的有这样的文件时才使用它,因为它也会尝试将 non-DICOM 文件作为 DICOM 处理,这可能会导致一些意外的异常。如前所述,这种情况下的错误与缺少前导码无关,而是与不正确的文件路径有关。

更新:
pydicom 的 2.1 版以来,此行为已更改。如果通过 None.

dcmread 现在将通过有意义的消息引发 TypeError