如何读取NIFTI格式图像(.nii文件)

在医学图像处理中,我们经常使用一种NIFTI格式图像(.nii文件),现在我们来看看

1 NIFTI格式图像

1.1 什么是NIFTI格式图像

在讲解什么是NIFTI(Neuroimaging Informatics Technology Initiative)格式之前,得先了解一下Analyze格式。Analyze格式储存的每组数据组包含2个文件,一个为数据文件,其扩展名为.img,包含二进制的图像资料;另外一个为头文件,扩展名为.hdr,包含图像的元数据。在FMRI的早期,Analyze格式最常用的格式,但现在逐渐被NIFTI格式所取代。Analyze格式主要不足就是头文件不能真正反映元数据。

标准NIFTI图像的扩展名是.nii,也包含了头文件及图像资料。由于NIFTI格式和Analyze格式的关系,因此NIFTI格式也可使用独立的图像文件(.img)和头文件(.hdr)。单独的.nii格式文件的优势就是可以使用标准的压缩软件(如gzip)进行压缩,而且一些分析软件包(比如FSL)可以直接读取和写入压缩的.nii文件(扩展名为.nii.gz)。

1.2 为什么会出现NIFTI格式图像

原来的ANALYZE 7.5 format图像格式缺少一些信息,比如没有方向信息,病人的左右方位等,如果需要包括额外的信息,就需要一个额外的文件,比如ANALYZE 7.5就需要一对<.hdr, .img>文件来保存图像的完整信息。因此,解决这个问题Data Format Working Group (DFWG) 将图像格式完整的定义为NIFTI格式。
详细了解NIFTI格式请参见: https://brainder.org/2012/09/23/the-nifti-file-format/

2 读取NIFTI格式图像

2.1 ITK-SNAP

推荐ITK-SNAP下载地址:http://www.itksnap.org/pmwiki/pmwiki.php?n=Downloads.SNAP3
在这里插入图片描述

可以看到:itk-snap获得了分别来自三个角度的视图(水平面、矢状面、冠状面)在这里插入图片描述

2.2 itkwidgets

详细请参见:https://pypi.org/project/itkwidgets/
在这里插入图片描述
在这里插入图片描述

2.3 simpleITK

这是使用最多的一种图像处理工具

import SimpleITK as sitk
from matplotlib import pyplot as plt


def showNii(img):
    for i in range(img.shape[0]):
        print(i)
        plt.imshow(img[i, :, :], cmap='gray')
        plt.show()


itk_img = sitk.ReadImage('./data/00_img.nii.gz')
img = sitk.GetArrayFromImage(itk_img)
print(img.shape)  # (88, 132, 175)表示各个维度切片的数量
showNii(img)

在这里插入图片描述

2.4 Nibabel

import matplotlib

matplotlib.use('TKAgg')
from matplotlib import pylab as plt
import nibabel as nib
from nibabel import nifti1
from nibabel.viewers import OrthoSlicer3D

example_filename = './data/00_img.nii.gz'
img = nib.load(example_filename)
print('img:\n', img)
print('img.header:\n', img.header['db_name'])  # 输出头信息

# 由文件本身维度确定,可能是3维,也可能是4维
width, height, queue = img.dataobj.shape
print(width, height, queue)  # 175 132 88

OrthoSlicer3D(img.dataobj).show()

num = 1
for i in range(0, queue, 11):
    img_arr = img.dataobj[:, :, i]
    plt.subplot(2, 4, num)
    plt.imshow(img_arr, cmap='gray')
    num += 1
plt.show()

在这里插入图片描述

参考文献

  1. https://blog.csdn.net/qq_33254870/article/details/100125788
  2. https://blog.csdn.net/alxe_made/article/details/80512423
<think>嗯,用户现在问的是如何将LUNA16的.npy格式数据转换为NIfTI.nii格式。我需要先回顾之前的对话,之前用户提供的是一个图像的头文件信息,包括维度、空间参数等,现在用户想用这些信息来转换格式。 首先,用户可能在做医学图像处理,比如使用LUNA16数据集,这个数据集通常用于肺结节检测,数据可能是CT扫描的。他们可能需要将NumPy数组转成NIfTI格式,可能是为了使用一些医学影像处理工具,如3D Slicer、FSL或SPM,这些工具通常支持NIfTI格式。 接下来,我需要考虑用户的具体需求。用户提供的头文件信息中有ElementSpacing、Offset、AnatomicalOrientation等,这些信息在转换过程中需要保留,以确保空间信息正确。同时,用户可能已经将原始数据(比如.raw文件)加载为NumPy数组,现在需要将这些数组保存为NIfTI,但需要正确的空间定位。 需要确认.npy数据的形状和方向是否与头文件中的DimSize一致。例如,头文件中DimSize是512x512x171,那么NumPy数组的形状可能是(171,512,512),但要注意是否需要进行转置,因为存储顺序可能不同(如z,y,x或x,y,z)。 另外,NIfTI格式使用affine矩阵来表示空间信息,这需要根据头文件中的Offset、ElementSpacing和AnatomicalOrientation来构建正确的affine矩阵。例如,Offset是原点位置,ElementSpacing是体素间距,AnatomicalOrientation是RAI,这会影响轴的方向。 可能需要使用Python库,如nibabel,来处理NIfTI文件的创建。用户可能需要将NumPy数组调整轴顺序以匹配NIfTI的标准方向,同时根据头文件中的参数设置affine矩阵。 还要注意数据类型是否正确,之前的头文件中提到ElementType是MET_SHORT,即int16,所以NumPy数组应该是dtype=np.int16,在保存时需保持一致。 潜在的问题可能包括轴顺序错误、affine矩阵构建不正确,导致在可视化时方向错误或位置偏移。需要指导用户如何验证生成的NIfTI文件是否正确,比如用3D Slicer打开检查解剖方向是否匹配。 用户可能没有提到但需要注意的细节:NumPy数组的存储顺序是否是C顺序或Fortran顺序,是否需要转置;AnatomicalOrientation中的RAI如何转换为NIfTI的坐标系(可能需要调整符号或轴的顺序)。 总结步骤应该是:加载.npy数组,调整形状和轴顺序,创建affine矩阵,使用nibabel保存为NIfTI,并验证结果。</think>是的,基于你提供的头文件信息,可以将 **LUNA16 的 `.npy` 格式数据(NumPy 数组)转换为 NIfTI 格式(`.nii`)**。以下是具体步骤和注意事项: --- ### **关键步骤** #### 1. **读取`.npy`数据** ```python import numpy as np data = np.load("input.npy") # 加载LUNA16的.npy文件 ``` #### 2. **调整数据形状与方向** - 根据头文件中的 `DimSize = 512 512 171`,确认数据形状应与 `(Z, Y, X)` 对应。 - 若 `.npy` 数据的维度顺序不符合 `(Z, Y, X)`,需调整轴顺序(例如转置): ```python data = np.transpose(data, (2, 1, 0)) # 假设原始顺序为 (X, Y, Z) ``` #### 3. **构建空间参数(Affine矩阵)** NIfTI 文件通过 **Affine矩阵** 定义体素到物理空间的映射。根据你提供的头文件参数: - **体素间距** `ElementSpacing = (0.488, 0.488, 1.8)` - **原点偏移** `Offset = (-127.756, -277.756, -351.5)` - **解剖方向** `AnatomicalOrientation = RAI`(右-前-上) 构建 Affine 矩阵: ```python import nibabel as nib affine = np.eye(4) affine[:3, :3] = np.diag([0.488, 0.488, 1.8]) # 体素间距 affine[:3, 3] = [-127.756, -277.756, -351.5] # 原点偏移 ``` > **注意**:若解剖方向(RAI)与标准 NIfTI 坐标系不一致,需调整符号或轴顺序。例如: > - RAI 对应 RAS(右-前-上),通常是 NIfTI 的默认方向,可能无需修改。 > - 若方向不符,需在 Affine 矩阵中调整轴符号或顺序。 #### 4. **保存为 NIfTI 文件** ```python nii_img = nib.Nifti1Image(data, affine) nib.save(nii_img, "output.nii") ``` --- ### **完整代码示例** ```python import numpy as np import nibabel as nib # 1. 读取.npy数据 data = np.load("input.npy") # 替换为实际路径 # 2. 调整轴顺序(根据实际存储顺序调整) data = np.transpose(data, (2, 1, 0)) # 假设原始为 (X, Y, Z) # 3. 构建Affine矩阵 affine = np.eye(4) affine[:3, :3] = np.diag([0.48828125, 0.48828125, 1.7999999523162842]) affine[:3, 3] = [-127.755859375, -277.755859375, -351.5] # 4. 保存为NIfTI nii_img = nib.Nifti1Image(data.astype(np.int16), affine) # 保持数据类型一致(MET_SHORT=int16) nib.save(nii_img, "output.nii") ``` --- ### **注意事项** 1. **轴顺序对齐** - 确保 NumPy 数组的维度顺序与 `DimSize` 的 `(Z, Y, X)` 一致。 - 不同库(如 SimpleITK、NiBabel)可能对轴顺序的定义不同,需通过可视化验证。 2. **方向一致性** - 使用 **3D Slicer** 或 **ITK-SNAP** 打开生成的 `.nii` 文件,检查解剖方向(RAI)是否正确。 - 若方向错误,可能需要调整 Affine 矩阵中的符号或轴顺序。 3. **数据类型匹配** - 原数据为 `MET_SHORT`(16位有符号整数),需确保 NumPy 数组的 `dtype` 是 `np.int16`。 4. **验证结果** ```python # 验证生成的NIfTI文件 loaded_nii = nib.load("output.nii") print(loaded_nii.header["pixdim"][1:4]) # 应输出体素间距 [0.488, 0.488, 1.8] ``` --- ### **常见问题** - **Q:转换后的NIfTI图像方向错误?** A:检查 Affine 矩阵的轴顺序和符号是否与解剖方向(RAI)匹配,必要时调整矩阵。 - **Q:数据形状不符?** A:确认 `.npy` 数据的原始维度顺序,可能需要使用 `np.transpose` 调整。 通过上述步骤,你可以将 LUNA16 的 `.npy` 数据正确转换为 NIfTI 格式,并保留原始的空间定位信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值