如何使用NiBabel编写彩色3D NITI?

时间:2016-11-10 18:10:37

标签: python 3d nifti

我用nibabel编写3D灰度.nii文件并在NIfTI查看器(Mango,MCIcron)中打开它们没有问题。但是我无法写出3D颜色,因为每个RGB平面都被解释为不同的体积。例如。这个输出:

import nibabel as nib
import numpy as np
nifti_path = "/my/local/path"
test_stack = (255.0 * np.random.rand(20, 201, 202, 3)).astype(np.uint8)
ni_img = nib.Nifti1Image(test_stack, np.eye(4))
nib.save(ni_img, nifti_path)

被视为3个独立的20x201x202卷。我也尝试将颜色平面放在第一个轴上(即np.random.rand(3,20,201,202)),但是得到了同样的问题。看一下似乎有一个“数据集”字段需要设置为128 24位RGB平面图像。关于nibabel的一个好处是它如何基于提供给它的numpy数组自动设置头。然而,这是一个模糊的情况,如果我打印标题信息,我可以看到它将数据类型设置为2(uint8),这可能是观众将其解释为单独的卷而不是RGB24的原因。我在API中没有看到任何官方支持来设置数据类型,但是 the documentation确实提到了那些“非常有勇气”的人对原始字段的访问。这样做,即

hdr = ni_img.header
raw = hdr.structarr
raw['datatype'] = 128

可用于更改标题值

print(hdr)

给出“datatype:RGB”,但在写

nib.save(ni_img, nifti_path)

我收到错误:

File "<python path>\lib\site-packages\nibabel\arraywriters.py", line 126, in scaling_needed
raise WriterError('Cannot cast to or from non-numeric types')
nibabel.arraywriters.WriterError: Cannot cast to or from non-numeric types

如果某些arr_dtype!= out_dtype会引发异常,因此可能是我对原始标头的黑客行为造成了一些不一致。

那么,有没有正确的方法呢?

2 个答案:

答案 0 :(得分:1)

感谢神经影像分析邮件列表中的matthew.brett,我能够像这样写出三维颜色NIfTI:

# ras_pos is a 4-d numpy array, with the last dim holding RGB
shape_3d = ras_pos.shape[0:3]
rgb_dtype = np.dtype([('R', 'u1'), ('G', 'u1'), ('B', 'u1')])
ras_pos = ras_pos.copy().view(dtype=rgb_dtype).reshape(shape_3d)  # copy used to force fresh internal structure
ni_img = nib.Nifti1Image(ras_pos, np.eye(4))
nib.save(ni_img, output_path)

答案 1 :(得分:0)

使用建议的方法有效,例如使用ITK-SNAP没问题,

# ras_pos is a 4-d numpy array, with the last dim holding RGB
shape_3d = ras_pos.shape[0:3]
rgb_dtype = np.dtype([('R', 'u1'), ('G', 'u1'), ('B', 'u1')])
ras_pos = ras_pos.copy().view(dtype=rgb_dtype).reshape(shape_3d)  # copy used 
#to force fresh internal structure
ni_img = nib.Nifti1Image(ras_pos, np.eye(4))
nib.save(ni_img, output_path)

但是,重新加载图像仅适用于get_data()

ni_img = nib.load(output_path)

# this will result in error
data = img.get_fdata()

# this will work fine, but get_data() is going to be removed.
data = img.get_data()

这很关键,因为在将来的版本中将删除get_data()。推荐仅使用get_fdata()。 get_fdata()方法当前存在错误,无法将RGB数据转换为有效的numpy数组。