import numpy as np
import os
import nibabel as nib
import matplotlib.pyplot as plt
from nilearn.image.image import _crop_img_to as crop_img_to
from nilearn.image.image import check_niimg
from nilearn.image import new_img_like
NII_DIR='./nii_dir'
#显示其中的一个slice
def read_nii_file(nii_path):
nii_image=nib.load(nii_path)
return nii_image
#需要将data数组的前两个维度转置以便正常显示
def nii_one_slice(image):
#W,H,C
image_arr=image.get_data()
print(type(image_arr))
#print(image_arr[125,160])
print(image_arr.shape)
image_2d=image_arr[:,:,85].transpose((1,0))
plt.imshow(image_2d, cmap = 'gray')
plt.show()
nii_image=read_nii_file(os.path.join(NII_DIR,'Brats18_2013_2_1','Brats18_2013_2_1_flair.nii.gz'))
#最大像素值和最小像素值
#0:background像素值
nii_arr=nii_image.get_data()
print(np.max(nii_arr),np.min(nii_arr))
nii_one_slice(nii_image)
输出:
1252 0
<class 'numpy.ndarray'>
(240, 240, 155)
根据设定的background像素值,综合所有模态和truth,得到前景区域
def get_foreground_from_set_of_files(set_of_files, background_value=0, tolerance=0.00001, return_image=False):
#set_of_files:('sub1-T1.nii.gz', 'sub1-T2.nii.gz', 'sub1-flair.nii.gz','sub1-t1ce.nii.gz','sub1-truth.nii.gz')
#image_file:sub1-T1.nii.gz
for i, image_file in enumerate(set_of_files):
#读取image无裁剪,无resize
print(image_file)
image = read_nii_file(image_file)
#根据设置的background值,综合所有模态和truth将image data数组中foreground位置设为True
is_foreground = np.logical_or(image.get_data() < (background_value - tolerance),
image.get_data() > (background_value + tolerance))
if i == 0:
foreground = np.zeros(is_foreground.shape, dtype=np.uint8)
#将is_foreground位置像素值设置为1
foreground[is_foreground] = 1
#返回image
if return_image:
return new_img_like(image, foreground)
#返回数组
else:
return foreground
set_of_files=(os.path.join(NII_DIR,'Brats18_2013_2_1',item) for item in ('Brats18_2013_2_1_flair.nii.gz','Brats18_2013_2_1_t1.nii.gz','Brats18_2013_2_1_t2.nii.gz','Brats18_2013_2_1_t1ce.nii.gz','Brats18_2013_2_1_seg.nii.gz'))
nii_foreground=get_foreground_from_set_of_files(set_of_files,return_image=True)
nii_one_slice(nii_foreground)
输出:
./nii_dir\Brats18_2013_2_1\Brats18_2013_2_1_flair.nii.gz
./nii_dir\Brats18_2013_2_1\Brats18_2013_2_1_t1.nii.gz
./nii_dir\Brats18_2013_2_1\Brats18_2013_2_1_t2.nii.gz
./nii_dir\Brats18_2013_2_1\Brats18_2013_2_1_t1ce.nii.gz
./nii_dir\Brats18_2013_2_1\Brats18_2013_2_1_seg.nii.gz
<class 'numpy.ndarray'>
(240, 240, 155)
得到裁剪的空间位置坐标范围
def get_slice_index(img,rtol=1e-8):
img = check_niimg(img)
data = img.get_data()
infinity_norm = max(-data.min(), data.max())
passes_threshold = np.logical_or(data < -rtol * infinity_norm,
data > rtol * infinity_norm) ##
if data.ndim == 4:
#any:对数组axis=-1上做或运算
passes_threshold = np.any(passes_threshold, axis=-1)
#np.where(condition):返回condition为Ture的索引,即坐标
coords = np.array(np.where(passes_threshold))
print(coords)
#每个维度起始位置,终止位置
start = coords.min(axis=1)
end = coords.max(axis=1) + 1
print(start,end)
# start和end不超过image
start = np.maximum(start - 1, 0)
end = np.minimum(end + 1, data.shape[:3])
#每个维度裁剪的slice切片对象:class slice(start, stop[, step])裁剪范围
slices = [slice(s, e) for s, e in zip(start, end)]
return slices
#W,H,C
crop = get_slice_index(nii_foreground)
print(crop)
输出:
[[ 49 49 49 ... 190 190 190]
[131 131 131 ... 153 153 153]
[ 47 48 49 ... 42 43 44]]
[49 41 14] [191 220 143]
[slice(48, 192, None), slice(40, 221, None), slice(13, 144, None)]
根据crop([slice(48, 192, None), slice(41, 221, None), slice(13, 143, None)])裁剪
图像
#根据每个维度裁剪的slice切片对象裁剪
nii_image_croped=crop_img_to(nii_image,crop,copy=True)
#放射矩阵4*4
print(nii_image_croped.affine)
nii_one_slice(nii_image_croped)
输出:
[[ -1. 0. 0. -48.]
[ 0. -1. 0. 199.]
[ 0. 0. 1. 13.]
[ 0. 0. 0. 1.]]
<class 'numpy.ndarray'>
(144, 181, 131)