关于在阅读nnUNet代码中的一些小细节的记录(一)

首先,感谢paper桑大佬关于nnUNet项目的解释,我从中获益很多。本片是关于nnUNet代码中我看到的认为可能比较重要的某些细节的记录。

1.推理阶段。在nnUNet/nnunet/preprocessing/cropping.py中 crop_to_nonzero函数

def crop_to_nonzero(data, seg=None, nonzero_label=-1):
    """

    :param data:
    :param seg:
    :param nonzero_label: this will be written into the segmentation map
    :return:
    """
    nonzero_mask = create_nonzero_mask(data)
    bbox = get_bbox_from_mask(nonzero_mask, 0)

    cropped_data = []
    for c in range(data.shape[0]):
        cropped = crop_to_bbox(data[c], bbox)
        cropped_data.append(cropped[None])
    data = np.vstack(cropped_data)

    if seg is not None:
        cropped_seg = []
        for c in range(seg.shape[0]):
            cropped = crop_to_bbox(seg[c], bbox)
            cropped_seg.append(cropped[None])
        seg = np.vstack(cropped_seg)

    nonzero_mask = crop_to_bbox(nonzero_mask, bbox)[None]
    if seg is not None:
        seg[(seg == 0) & (nonzero_mask == 0)] = nonzero_label
    else:
        nonzero_mask = nonzero_mask.astype(int)
        nonzero_mask[nonzero_mask == 0] = nonzero_label
        nonzero_mask[nonzero_mask > 0] = 0
        seg = nonzero_mask
    return data, seg, bbox

data中值为0的对于nonzero_mask中都设置为了-1.(当然其中create_nonzero_mask函数时用到了binary_fill_holes,填充了一部分)

 

2.推理阶段。在nnUNet/nnunet/preprocessing/preprocessing.py中311行

data, seg, properties = self.resample_and_normalize(data, target_spacing, properties, seg, force_separate_z=force_separate_z)

实现对数据的重采样和归一化。

 

3.推理阶段: 在nnUNet/nnunet/preprocessing/preprocessing.py中150行

reshaped_data.append(resize_fn(data[c, slice_id], new_shape_2d, order, cval=cval, **kwargs))

里对每一张512*512进行了重采样。 这里的resize_fn代表的是skimage.transform.resize() 函数其中的order=3.

值得一提的是。如果这是对掩码的重采样的话,resize_fn代表的是batchgenerators.augmentations.utils.resize_segmentation() 其中order=3,原因是为了防止([0, 0, 2] -> [0, 1, 2])的情况。因为掩码可能是0代表背景,1代表前景,2代表前景中的病灶。这0到1就是使一个背景变前景。

4.推理阶段:在nnUNet/nnunet/preprocessing/preprocessing.py中174行

reshaped_final_data.append(map_coordinates(reshaped_data, coord_map, order=order_z, cval=cval,mode='nearest')[None])

z轴方向,用的是scipy.ndimage.interpolation.map_coordinates() 函数来出处理添加中间的层数(做一个3dmap坐标。z轴3d矩阵,x一个,y一个。填充坐标最近的原坐标值)。实例如下

#原数据
reshaped_data[0][300][300]=-94.4081754097679
reshaped_data[1][300][300]=-38.33892068143663

reshaped_data[0][301][300]=-100.75139288087729


#map_coordinates采样后
#z轴在变,但值还是那些值(分辨率改变)
reshaped_final_data[0][0][0][300][300]=-94.4081754097679
reshaped_final_data[0][0][1][300][300]=-94.4081754097679
reshaped_final_data[0][0][2][300][300]=-94.4081754097679
reshaped_final_data[0][0][3][300][300]=-38.33892068143663
reshaped_final_data[0][0][4][300][300]=-38.33892068143663
reshaped_final_data[0][0][5][300][300]=-38.33892068143663
reshaped_final_data[0][0][6][300][300]= 46.13715590124825
#x轴不变,x分辨率不变。
reshaped_final_data[0][0][0][301][300]=-100.75139288087729

5.2d数据转nii格式阶段:在/home/pacs/nnUNet/nnunet/dataset_conversion/Task120_Massachusetts_RoadSegm.py中66行

transform=lambda x: (x == 255).astype(int)

单标签:

import numpy as np

a=[[0,60,120,180,240],[0,0,0,0,0],[0,0,0,0,0],[240,180,120,60,0]]
a=np.array(a)
transform=lambda x: (x == 240).astype(int)
b=transform(a)
print(b)

[[0 0 0 0 1]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [1 0 0 0 0]]

 

多标签:

import numpy as np

a=[[0,60,120,180,240],[0,0,0,0,0],[0,0,0,0,0],[240,180,120,60,0]]
a=np.array(a)
transform=lambda x: (x == 240).astype(int)*1
transform1=lambda x: (x == 180).astype(int)*2
transform2=lambda x: (x == 120).astype(int)*3
transform3=lambda x: (x == 60).astype(int)*4
b=transform(a)+transform1(a)+transform2(a)+transform3(a)
print(b)


[[0 4 3 2 1]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [1 2 3 4 0]]

 

你可能感兴趣的:(深度学习,nnUNet)