当前位置:   article > 正文

医学nii图像 预处理——图像裁剪 重采样 灰度区域 归一化 修改图像尺寸_nii图像裁剪

nii图像裁剪

鄙人主要研究方向为医学图像配准,在使用CT数据集之前需要对数据进行预处理。
常规预处理步骤:(*代表本代码有)
1.裁剪出ROI区域
目的:减小图像尺寸,减小内存消耗,减小无关信息,可提高实验精度
2.重采样
一般会重采样到各向同性,例如,将图像重采样到每体素代表1
1
1mm实际体积
3.CT转HU,斜率,截距.[CT图像专有,本文代码没写这个]
*4.截取ROI灰度区域
当处理的图像为肺部图像时,也称为截取肺窗,即肺所在灰度范围,常见肺窗[窗宽:900,窗位:-550],宽肺窗[窗宽:1600,窗位:-600]
*5.归一化
目的:防止梯度防炸
6.resize图像尺寸
由算法(有些算法要求输入图片尺寸统一,有些算法则需要保证原图)或电脑性能(显存小,只能缩小图片咯~)决定

直接上代码

import nibabel as nib
import numpy as np
import torch

def get_gray_range(image):
    '获取图像信息:最大最小值'
    image = np.reshape(image, (1, image.shape[0] * image.shape[1] * image.shape[2]))
    image_gray_list = image.tolist()[0]
    image_gray_list.sort()  # 默认升序排列灰度值
    point_num = len(image_gray_list)
    min_num = round(point_num * 0.05)
    max_num = round(point_num * 0.95)
    min_gray_value = image_gray_list[min_num]
    max_gray_value = image_gray_list[max_num - 1]

    return min_gray_value, max_gray_value

def resampling_isotropic(data,voxel,spacing=[1, 1, 1]):
    """
    利用上下采样原理,恢复到各向同性
    :param data: 输入图像
    :param spacing: 各向同行或异性,默认为1*1*1
    :return:
    """
    # 获取图像信息:长宽高;
    height, weight, deepth = data.shape

    # 输出图的size
    size_X = int(height*voxel[0]/spacing[0])
    size_Y = int(weight*voxel[1]/spacing[1])
    size_Z = int(deepth*voxel[2]/spacing[2])

    # ndarray转torch;增加两维,目的是可以在"上下采样"中使用三线性插值法
    data = torch.tensor(data).unsqueeze(0).unsqueeze(0)

    # torch转.float32
    data = data.to(torch.float32)

    """
    函数说明:
    torch.nn.functional.interpolate(input, size=None, scale_factor=None, mode='nearest', align_corners=None, recompute_scale_factor=None)
    
    input (Tensor) – the input tensor
    size (int or Tuple[int] or Tuple[int, int] or Tuple[int, int, int]) – output spatial size.
    scale_factor (float or Tuple[float]) – 空间大小的乘数。如果scale_factor是一个tuple,它的长度必须匹配input.dim()。
    mode (str) – algorithm used for upsampling: nearest(Default), linear (3D-only), bilinear, bicubic (4D-only), trilinear (5D-only), area
    align_corners (bool, optional):几何上,我们把输入和输出的像素看作正方形而不是点。默认值:False
    如果设置为True,输入和输出张量将由它们的角像素中心点对齐,并保留角像素的值。
    如果设置为False,则输入和输出张量由它们的角像素的角点对齐,并且插值对边界外值使用边值填充,使得在scale_factor保持不变的情况下,该操作与输入大小无关。
    这只在mode is 'linear', 'bilinear', 'bicubic' or 'trilinear'时才有效果。
    recompute_scale_factor (bool, optional) :重新计算用于插值计算的scale_factor。
    如果为True,则必须传入scale_factor,并使用scale_factor计算输出大小。计算出的输出大小将用于为插值推断新的尺度。
    注意,当scale_factor是浮点数时,由于舍入和精度问题,它可能与重新计算的scale_factor不同。
    如果为False,那么size或scale_factor将直接用于插值。
    """
    data = torch.nn.functional.interpolate(data,
                                            size=[size_X,size_Y,size_Z],
                                            mode='trilinear',
                                            align_corners=False)
    return data[0, 0, :, :, :]

if __name__ == "__main__":
    """
    预处理主程序
    需修改的参数:
    img_name:图片名称
    old_path:数据集旧路径
    new_path:数据集新路径
    """

    img_path = old_path + img_name
    # 打开nii格式
    img = nib.load(img_path)
    img_data = np.asarray(img.dataobj)

    # 把仿射矩阵和头文件都存下来
    img_affine = img.affine
    img_hdr = img.header

    # 获取图像信息:最大最小值
    img_min, img_max = get_gray_range(img_data)

    # 获取图像信息:长宽高;
    height, weight, deepth = img_data.shape

    # 获取图像信息:voxel spacing,
	voxel = [img_hdr['pixdim'][1]]
    voxel.append(img_hdr['pixdim'][2])
    voxel.append(img_hdr['pixdim'][3])

    # 1.裁剪出感兴趣ROI区域,自定义裁剪范围数据
    ROIrange_XYZ=[40,440,20,240,10,130] 
    xmin=ROIrange_XYZ[0]
    xmax=ROIrange_XYZ[1]
    ymin=ROIrange_XYZ[2]
    ymax=ROIrange_XYZ[3]
    zmin=ROIrange_XYZ[4]
    zmax=ROIrange_XYZ[5]
    img_crop = img_data[xmin:xmax,ymin:ymax,zmin:zmax]

    # 2.重采样。可以恢复到各向同性[1,1,1]
    resample_spacing=[1,1,1]
    img_isotropic = resampling_isotropic(data=img_crop,voxel=voxel,spacing=resample_spacing)

    # 修改NIfTI affines
    scaling_affine = np.diag([resample_spacing[0], resample_spacing[1], resample_spacing[2], 1])

    # 3.裁剪出肺窗
    TonalRange=[-1000,-100]
    clamp_min = TonalRange[0] if img_min <= TonalRange[0] else img_min
    clamp_max = TonalRange[1] if img_max >= TonalRange[1] else img_max
    intrange = clamp_max - clamp_min
    img_clamp = torch.clamp(img_isotropic,min=clamp_min,max=clamp_max)

    # 4 归一化处理,灰度范围-》[0,1]
    img_normalize = (img_clamp-clamp_min) / intrange

    # 5 保存为nii格式
    # NiBabel网址 https://nipy.org/nibabel/manual.html
    img_new = nib.Nifti1Image(img_normalize, scaling_affine, img_hdr)
    img_new_path = new_path + img_name
    nib.save(img_new, img_new_path)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/45519
推荐阅读
相关标签
  

闽ICP备14008679号