程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

python 筆記:打開nii格式(nibabel 庫)

編輯:Python

1 nii格式介紹

 1.0 Analyze 格式

在解釋NII(NIFTI,neuroimaging information technology initiative)格式之前,我們需要先知道一下Analyze格式。

每一個Analyze格式的數據包含了兩個文件:帶有二進制圖像信息的.img,包含圖像元數據的頭文件.hdr

但是,Analyze的頭文件不能很真實地反應元數據(比如沒有方向信息,eg在左邊還是在右邊),於是NIFTI格式文件應運而生

1.1 組成部分

nii格式(nifti格式的擴展)是為多維神經影像學發明的。一個nii格式主要包含三部分:hdr, ext, img

  • hdr
    • header,數據頭
    • 這部分數據長度是固定的,當然不同版本可能規定的長度不同,但是同一版本的多個nii文件是相同的。
    • header裡包含的信息有:
      • --維度,至少三個維度,x,y,z,單位是毫米。還有可能有第四個維度,就是時間。這部分儲存的主要是四個數字。
      • --voxel size(體素大小):毫米單位的x,y,z大小。
      • --數據類型,一般是int16,這個精度不夠,最好使用double類型。
      • Form和轉換矩陣,每一個Form都對應一個轉換矩陣。
        •  轉換矩陣可以輕松分清圖像的左右,作用是將體素索引(i,j,k)轉換為空間位置(x,y,z)。
        • 具體使用方法是轉換矩陣乘以一個包含(i,j,k)的矩陣,就可以得到一個包含(x,y,z)的矩陣。
          •  體素可以類比成二維圖像中的像素。體素就是固定分辨率的三維柵格地圖
  • ext
    • extension
    • 是自己可以隨意定義數據的部分,可以自己用。
  • img
    • image
    • 儲存3D或者4D的圖像數據
    • .hdr 和 .img可以用單文件.nii存儲

1.2 坐標

醫學影像數據有兩種格式,dicom和nii格式,他們定義了不同的方向

2 打開圖像

2.1 ITK-SNAP軟件

注意:使用這個軟件的時候,路徑中不能有中文 

三視圖 

 

3 nibabel (python庫)

3.1 基本操作

3.1.1 導入nii

import nibabel as nib
filename = 'CTC-1835078273_seg.nii'
img = nib.load(filename)
img.shape
#(512, 512, 539)

一個nibable 圖像有三部分組合而成:

  • image數據,三維/四維圖像
  • 一個仿射數組 affine,image數據在參考空間中的位置
  • image元數據 (header)

3.1.2 獲得圖像的ndarray類型數據 

data = img.get_fdata()
data.shape,type(data)
#((512, 512, 539), numpy.memmap)

 3.1.3 創建新image

至少需要一些image 數據 和一個image 坐標轉換矩陣(affine)

import numpy as np
data = np.random.randint((32, 32, 15, 100), dtype=np.int16)
img = nib.Nifti1Image(data, np.eye(4))
nib.save(img, 'exa.nii') 

  

這裡numpy.memmap是內存映像文件。它是一種將磁盤上的非常大的二進制數據文件當做內存中的數組進行處理的方式。它允許將大文件分成小段進行讀寫,而不是一次性將整個數組讀入內存。

memmap也擁有跟普通數組一樣的方法,因此,基本上只要是能用於ndarray的算法就也能用於memmap。
 

3.2  坐標系和affine

在官方文檔中,提供了一個人大腦的MRI圖像。

import nibabel as nib
epi_img = nib.load('someones_epi.nii.gz')
epi_img_data = epi_img.get_fdata()
epi_img_data.shape
#(53, 61, 33)

[EPI數據]我們看看數組的第一維、第二維和第三維上的切片。

import matplotlib.pyplot as plt
def show_slices(slices):
""" Function to display row of image slices """
fig, axes = plt.subplots(1, len(slices))
for i, slice in enumerate(slices):
axes[i].imshow(slice.T, cmap="gray", origin="lower")
slice_0 = epi_img_data[0, :, :]
slice_1 = epi_img_data[:, 0, :]
slice_2 = epi_img_data[:, :, 0]
show_slices([slice_0, slice_1, slice_2])
plt.suptitle("Center slices for EPI image") 

 image維度是(53, 61, 33),可以想成是53張61*33的圖,可以想成是61張53*33的圖,還可以想成是33張53*61的圖

[結構數據(解剖)]

anat_img = nib.load('someones_anatomy.nii.gz')
anat_img_data = anat_img.get_fdata()
print(anat_img_data.shape)
#(57, 67, 56)
show_slices([anat_img_data[0, :, :],
anat_img_data[:, 0, :],
anat_img_data[:, :, 0]])
plt.suptitle("Center slices for anatomical image")

  

通常情況下,我們有不同的解剖掃描視野,因此解剖圖像具有不同的形狀、大小和方向。

3.2.1 體素坐標

體素是具有體積的像素。

在上面的代碼中,來自 EPI 數據的 slice_0 是來自 3D 圖像的 2D 切片。 切片灰度圖像中的每個像素也代表一個體素,因為這個 2D 圖像代表了 3D 圖像中具有一定厚度的切片。

因此,3D 陣列也是體素陣列。 對於任何數組,我們都可以通過索引來選擇特定的值。 例如,我們可以像這樣獲取 EPI 數據數組中中間體素的值:

epi_img_data[0,0,0]
#10.755071640014648

[0,0,0]就是體素坐標

3.2.2 體素坐標和空間點

體素坐標幾乎不告訴我們數據在掃描儀中的位置來自何處。 例如,假設我們有體素坐標 (26, 30, 16)。 如果沒有更多信息,我們不知道這個體素位置是在大腦的左側還是右側,還是來自掃描儀的左側或右側。 這是因為掃描儀允許我們在幾乎任何任意位置和方向收集體素數據。

比如我們對EPI圖,將掃描儀稍微旋轉一下,得到紅色框內的部分

  

我們進行了解剖和 EPI 掃描,稍後我們肯定希望能夠將 somes_epi.nii.gz 中的數據與someones_anatomy.nii.gz 相關聯。目前我們不能輕易做到這一點,因為我們收集到的解剖圖像與 EPI 圖像具有不同的視野和方向。所以體素坐標暫時不能一一對應。 

我們通過跟蹤體素坐標與某些參考空間的關系來解決這個問題。具體而言,仿射陣列(affine)存儲圖像數據中的體素坐標與參考空間中的坐標之間的關系

“參考空間”中的“空間”是什麼意思? 該空間由一組有序的軸定義。 對於我們的 3D 空間世界,它是一組 3 個獨立的軸。 我們可以通過選擇這些軸來決定我們想要使用的空間。 我們需要選擇軸的原點、方向和單位。(xyz-坐標軸,單位毫米)

3.2.3 affine matrix

我們希望將體素坐標(i,j,k)轉換到參考空間坐標(x,y,z),即(x,y,z)=f(i,j,k)

而基本的矩陣乘法,可以滿足

坐標軸伸縮 旋轉

圍繞第一個坐標軸旋轉

  

圍繞第二個坐標軸旋轉

  

  

圍繞第三個坐標軸旋轉

  

這幾個基本的操作相結合(矩陣乘法),就可以實現坐標軸的變換 

上面完成了坐標軸的對應,但是體素的原點(0,0,0)對應的不一定是參考空間的(0,0,0)點,假設對應的是參考空間中的(a,b,c)坐標,那麼,體素中的(i,j,k)對應的是參考空間中的(x,y,z)    

3.2.4 獲得image的affine

  

參考文獻 

NII - Just Solve the File Format Problem (archiveteam.org)

How to read NIFTI format image (. nii file) (programmer.group)

什麼是體素(Voxel)? - 知乎 (zhihu.com)


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved