[3DUNetMRI图像预处理2]综合4个模态+truth和设置的background像素值获取foreground,并裁剪

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)

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值