KITS+肾脏肿瘤预处理+重采样+窗体变换+强度裁剪

您所在的位置:网站首页 gee重采样到1x1度 KITS+肾脏肿瘤预处理+重采样+窗体变换+强度裁剪

KITS+肾脏肿瘤预处理+重采样+窗体变换+强度裁剪

2024-07-14 07:00| 来源: 网络整理| 查看: 265

摘要

目前正在做肾脏肿瘤的预处理问题,比赛地址。 KiTS19 年比赛的 结果。 JunMa大佬在自己的知乎里面给出了自己的看法和对于论文的学习与展望。

我最近正在解决数据预处理的问题,论文的数据预处理分为了重采样,spacing 到 3.22mmx1.62mmx1.62mm,然后将灰度值cut off到[-79,304],然后将cut off 之后的数据进行z-score(subtract 101 and divide by 76.9 to bring the intensity values in a range that is more easily processed by CNNs)。最后将输入神经网络的数据大小定为80x160x160。

重采样

首先强调一下,我对于论文的复现来自于我对于论文的解读以及自己代码水平,不一定对,但是提供一个思路 我一开始对于spacing到3.22mmx1.62mmx1.62mm表示十分的不理解,像素之间的距离难道不都是1吗?像素距离和实际测量的毫米有什么关系,后来我才知道,CT图像里面是保存有图像的pixdim信息的。具体代码如下

#img_name 就是一个nii.gz文件的地址 img = nibabel.load(img_name) pix_dim = (img.header.structarr['pixdim'][1], img.header.structarr['pixdim'][2], img.header.structarr['pixdim'][3]) print(pix_dim)

这样就可以读取pixdim数据我的第一个图片的数据是(0.5mm, 0.9199219mm,0.9199219mm)也就是说它的实际spacing是这个。使用skimage里面的transform.rescale()就可以把数据处理成自己想要得spacing,具体写法如下(对于image的操作)

from skimage import transform target_resolution = (3.22,1.62,1.62) img = np.array(img.get_data()) scale_vector = ( pix_dim[0]/target_resolution[0], pix_dim[1]/target_resolution[1], pix_dim[2]/target_resolution[2] ) """ order = 1 样条插值的顺序,必须是在0-5范围内,默认是1,详情参见skimage.transform.warp 这个很重要 mode = {'constant','edge','symmetric','reflect','warp'}可选输入边界之外的点根据到给定的模式,模式匹配行为'numpy.pad' cval 与模式constant结合使用,外部值图像边界 剪辑 : bool 可选, 是否将输出剪辑到输入值范围,这是默认启用的,因为高阶线性插值可能产生超出给定输入值的范围。 preserve_range : bool 可选 是否保持原始值的范围。否则输入图像根据img_as_float的约定进行转换 详情: https://scikit-image.org/docs/dev/user_guide/data_types.html multichannel : bool 可选 图像的最后一个轴是否被解释为多个通道或者空间维度。 anti_aliasing : bool 可选 是否用高斯滤波器来平滑图像,缩小比例。将图像下采样到避免解释为多个渠道或者其他空间维度避免混叠伪影 anti_aliasing_sigma : {float, tuple of floats} optional 高斯滤波的标准差,以避免混叠伪影,默认情况下,此值选择为(1-2)/2,其中s是缩小比例因子 """ yinzi = transform.rescale(img, scale_vector,order=1, mode='constant', cval=0, clip=True, preserve_range=True, multichannel=False, anti_aliasing=True, anti_aliasing_sigma=None)

scale_vector 是 pixdim和target_resolution的比值,对于这个rescale真的有很多参数,如果不想改变原来的值就把order=0,并且把anti_aliasing=False ,并且把preserve_range=True(这个真的特别重要), 因为如果不这样的话,mask里面的数据只有[0,1,2],rescale之后数据就会变得很乱很乱,对于mask的操作如下

img = nibabel.load(img_name) print(img.shape) pix_dim = (img.header.structarr['pixdim'][1], img.header.structarr['pixdim'][2], img.header.structarr['pixdim'][3]) print('pix_dim',pix_dim) img = np.array(img.get_data()) print('non_transpos_shape',img.shape) print(np.unique(img)) target_resolution = (3.22,1.62,1.62) scale_vector = ( pix_dim[0] / target_resolution[0], pix_dim[1] / target_resolution[1], pix_dim[2] / target_resolution[2] ) img = img.astype(np.float) print('img.dtype', img.dtype) print(np.unique(img)) # uint8 # 这里把uint8转换成了float64了 yinzi = transform.rescale(img, scale_vector,order=0, mode='constant', cval=0, clip=True, preserve_range=True, multichannel=False, anti_aliasing=False, anti_aliasing_sigma=None)

这里比较建议大家去读一读源码里面的注释,然后参考输入输出类型的解释的官方页面进行学习。

窗体变换+强度裁剪

强度裁剪

ct_array[ct_array 304.0] = 304.0

z-score

newimg = (ct_array - 101) / float(76.9) crop成(80,160,160)

这个真的是自己瞎编了,我用最传统的赋值方法做的,具体对不对我也不知道了 代码:

def z_crop(img_array,crop_array,z,xy): if z >= 80 and xy >= 160: side = z - 80 startz = side//2 endnum = side - startz endz = z - endnum startxy = (xy-160)//2 endxy = xy - ((xy-160)-startxy) crop_array[:,:,:] = img_array[startz:endz,startxy:endxy,startxy:endxy] elif z>=80 and xy


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3