DICOM 到 Nifti 元数据未传输
DICOM to Nifti metadata not transfering
我正在尝试获取一些 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 之前打印 header 时显示 [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)
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. ]]
如果您使用 SimpleITK 读取 Dicom 系列,它将正确读取 Dicom 元数据。
以下是如何阅读 Dicom 图像系列的示例:
https://simpleitk.readthedocs.io/en/master/link_DicomSeriesReader_docs.html
如果输出文件名有“.nii”后缀,它会将卷写为 Nifti 文件。
您需要直接指定像素间距和阵列形状,假设您有 512x512x128 的 3D 体积,体素间距为 0.5 x 0.5 x 2.5 毫米,以及单位方向矩阵,请参见下面的示例:
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 中打开它,给出以下结果:
我正在尝试获取一些 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 之前打印 header 时显示 [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)
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. ]]
如果您使用 SimpleITK 读取 Dicom 系列,它将正确读取 Dicom 元数据。
以下是如何阅读 Dicom 图像系列的示例:
https://simpleitk.readthedocs.io/en/master/link_DicomSeriesReader_docs.html
如果输出文件名有“.nii”后缀,它会将卷写为 Nifti 文件。
您需要直接指定像素间距和阵列形状,假设您有 512x512x128 的 3D 体积,体素间距为 0.5 x 0.5 x 2.5 毫米,以及单位方向矩阵,请参见下面的示例:
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 中打开它,给出以下结果: