【问题标题】:DICOM to Nifti metadata not transferingDICOM 到 Nifti 元数据未传输
【发布时间】:2020-08-04 21:09:21
【问题描述】:

我正在尝试获取一些 DICOM 堆栈并将它们转换为 Nifti 文件。当我进行转换并在 3D 查看器中打开新的 Nifti 文件时,体积在 z 方向上被粉碎在一起。 Nifti 文件不知道切片之间的间距是多少。据我了解,imageio.volread() 不会读取元数据。我尝试使用pydicom.filereader.dcmread(),但它只读取一个文件。转换格式时如何将元数据从 DICOM 堆栈复制到 Nifti 文件?

import nibabel as nib
import imageio
import numpy as np
import os, sys

DIR = '\\all scans\\'
savefold = '\\nifti\\'

for root, dirs, files in os.walk(DIR):
    for directory in dirs:
        vol = imageio.volread(DIR + directory).astype(int)
        vol = np.transpose(vol, (2,1,0)).astype(int)
        niftisave = nib.Nifti1Image(vol, affine=np.eye(4))
        nib.save(niftisave, os.path.join(savefold + directory) + '.nii')

更新:

我正在使用Nifti1Header 并设置我的体素间距,但是当我在其他程序中保存并打开文件时,体素间距仍然是 1x1x1。当我在保存 pixdim 之前打印标题时显示[1. 0.09 0.09 0.09 1. 1. 1. 1. ]

header = nib.Nifti1Header()
OM = np.eye(4)
header.set_data_shape((224,352,224))
voxel_spacing = ((.09,.09,.09))
header.set_zooms(voxel_spacing)
header.set_sform(OM)
header.set_dim_info(slice = 2)

vol=imageio.volread(source) 

ROI_save = nib.Nifti1Image(vol, OM, header=header)
print(ROI_save.header)

标题:

<class 'nibabel.nifti1.Nifti1Header'> object, endian='<'
sizeof_hdr      : 348
data_type       : b''
db_name         : b''
extents         : 0
session_error   : 0
regular         : b''
dim_info        : 48
dim             : [  3 224 352 224   1   1   1   1]
intent_p1       : 0.0
intent_p2       : 0.0
intent_p3       : 0.0
intent_code     : none
datatype        : float32
bitpix          : 32
slice_start     : 0
pixdim          : [1.   0.09 0.09 0.09 1.   1.   1.   1.  ]
vox_offset      : 0.0
scl_slope       : nan
scl_inter       : nan
slice_end       : 0
slice_code      : unknown
xyzt_units      : 0
cal_max         : 0.0
cal_min         : 0.0
slice_duration  : 0.0
toffset         : 0.0
glmax           : 0
glmin           : 0
descrip         : b''
aux_file        : b''
qform_code      : unknown
sform_code      : aligned
quatern_b       : 0.0
quatern_c       : 0.0
quatern_d       : 0.0
qoffset_x       : 0.0
qoffset_y       : 0.0
qoffset_z       : 0.0
srow_x          : [1. 0. 0. 0.]
srow_y          : [0. 1. 0. 0.]
srow_z          : [0. 0. 1. 0.]
intent_name     : b''
magic           : b'n+1'

仿射:

np.eye(4)
--->[[1. 0. 0. 0.]
     [0. 1. 0. 0.]
     [0. 0. 1. 0.]
     [0. 0. 0. 1.]]

所需的仿射:

[[-0.09  0.    0.   -0.  ]
 [ 0.   -0.09  0.   -0.  ]
 [ 0.    0.    0.09  0.  ]
 [ 0.    0.    0.    1.  ]]

【问题讨论】:

    标签: metadata pydicom nifti medical-imaging


    【解决方案1】:

    您需要直接指定像素间距和阵列形状,假设您有 512x512x128 的 3D 体积,体素间距为 0.5 x 0.5 x 2.5 mm,单位方向矩阵参见下面的示例:

    from nibabel import Nifti1Header, Nifti1Image
    
    img_array = np.zeros((512, 512, 128))
    
    voxel_spacing = [0.5, 0.5, 2.5, 1]
    OM = np.eye(4)
    OM = OM * np.diag(voxel_spacing)
    
    header = Nifti1Header()
    header.set_data_shape((512, 512, 128))
    header.set_dim_info(slice=2)
    header.set_xyzt_units('mm')
    
    nifti =  Nifti1Image(img_array, OM, header=header)
    

    更新。 使用nibabel.save(或img.to_filename)保存文件并在MRIcron https://people.cas.sc.edu/rorden/mricron/index.html中打开,得到如下结果:

    【讨论】:

    • 当我在其他程序中打开保存的 nifti 文件时,我的体素间距仍显示为 1x1x1。我在保存之前更新了帖子以显示标题信息。
    • 如何保存 nifti 文件以及使用哪个程序打开它?
    • 尝试添加header.set_xyzt_units('mm')(我更新了答案)
    • 发现了问题。这是affine = np.eye(4)。生成的矩阵不适合我的间距。如果您将仿射设置为具有调整值的矩阵,则它可以工作。我会更新问题,以便您了解我的意思。显然simpleITK 会在您设置间距时处理此问题,但nibabel 会让您手动设置。
    • 我认为问题在于标题覆盖了 Nifti1Image 创建中的 OM。我编辑了答案(删除 header.set_sform(...)),现在它应该产生正确的结果。
    【解决方案2】:

    如果您使用 SimpleITK 读取 Dicom 系列,它将正确读取 Dicom 元数据。

    以下是如何阅读 Dicom 图像系列的示例:

    https://simpleitk.readthedocs.io/en/master/link_DicomSeriesReader_docs.html

    如果输出文件名有“.nii”后缀,它会将卷写为 Nifti 文件。

    【讨论】:

      猜你喜欢
      • 2022-06-10
      • 1970-01-01
      • 1970-01-01
      • 2015-07-24
      • 1970-01-01
      • 1970-01-01
      • 2014-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多