nnUNet实战(一):CREMI挑战赛简单实践

nnUNet实战

文章目录

一、云服务器租赁

由于本人的笔记本计算资源有限,实验室的服务器资源师兄师姐经常使用,因此这里选择云服务器进行学习尝试。

近年来的云服务器资源比较丰富,阿里、华为等大厂甚至是移动都有相应的服务器资源。我用过阿里云、华为云、AutoDL这三种云服务器。按照我的使用感受,华为云由于学校赠送代金券,而且镜像方面比较全面,数据存储服务等都是上乘,使用的比较舒服,但个人使用的话GPU价格还是有点小高。阿里云用的时间比较久远,当时好像有图形化界面,对于新手比较友好。AutoDL是我最近在用的云服务器,其中的环境都比较高,python3.8为主,不过好处是可以无卡开机,并且网盘上传。这里就以AutoDL为主。
打开AutoDL官网
https://www.autodl.com/

nnUNet实战(一):CREMI挑战赛简单实践
点击右上角的控制台
nnUNet实战(一):CREMI挑战赛简单实践
点击左上角的我的实例,进行服务器租赁。
nnUNet实战(一):CREMI挑战赛简单实践
之后进行相应的环境选择
nnUNet实战(一):CREMI挑战赛简单实践
创建完成后可以先关机,之后用无卡模式启动,比较我们后面还要安装一些外围环境并准备数据。

; 二、nnUNet安装

nnUNet官网地址:
https://github.com/MIC-DKFZ/nnUNet

1.前期准备(文件目录、环境检查)

点击更多,选择无卡模式开机。

nnUNet实战(一):CREMI挑战赛简单实践
点击jupyterLab进入控制页面,选择终端进行nnUNet环境的安装。
由于AutoDL中,存储空间分为数据盘和系统盘,如果将所有的数据都放在默认的系统盘的话,之后会出现系统盘数据溢出,不能关机的情况,因此我们先跳转到数据盘autodl-tmp,并创建一个文件夹nnUNetFrame,专门存放nnUNet数据。之后跳转至相应的文件夹中
cd autodl-tmp/nnUNetFrame

之后按照git中的教程进行安装
查看pytorch版本:

python -c 'import torch;print(torch.backends.cudnn.version())'
python -c 'import torch;print(torch.__version__)'

nnUNet实战(一):CREMI挑战赛简单实践

2.安装nnUNet

根据使用案例安装 nnU-Net:
用作标准化基线、开箱即用的分割算法,或用于使用预训练模型运行推理:

pip install nnunet

用作集成框架(这将在计算机上创建 nnU-Net 代码的副本,以便您可以根据需要对其进行修改):

git clone https://github.com/MIC-DKFZ/nnUNet.git
cd nnUNet
pip install -e .

这里使用第二种方法

nnUNet实战(一):CREMI挑战赛简单实践
有时候会出现
failed: The TLS connection was non-properly terminated.

关机重启,多试几次就可以了

nnUNet实战(一):CREMI挑战赛简单实践
(可选)安装隐藏层。hiddenlayer使nnU-net能够生成它生成的网络拓扑的图(参见模型训练)。要安装隐藏层,请运行以下命令:
pip install --upgrade git+https://github.com/FabianIsensee/hiddenlayer.git@more_plotted_details

nnUNet实战(一):CREMI挑战赛简单实践
此外,还需要安装一些额外库
conda install h5py

nnUNet实战(一):CREMI挑战赛简单实践

3.数据整理

在已有的nnUNetFrame文件夹中新建DATASET文件夹

nnUNet实战(一):CREMI挑战赛简单实践
在DATASET文件夹中新建三个新的子文件夹
nnUNet_raw
nnUNet_preprocessed
nnUNet_trained_models
之后增加系统变量,临时增加系统变量可以使用如下命令:
export nnUNet_raw_data_base="/root/autodl-tmp/nnUNetFrame/DATASET/nnUNet_raw"
export nnUNet_preprocessed="/root/autodl-tmp/nnUNetFrame/DATASET/nnUNet_preprocessed"
export RESULTS_FOLDER="/root/autodl-tmp/nnUNetFrame/DATASET/nnUNet_trained_models"

永久改变可以参考这里链接
https://github.com/MIC-DKFZ/nnUNet/blob/master/documentation/setting_up_paths.md

如果有些云服务器没有更改系统文件的权限,使用如下方法:
首先打开
autodl-tmp/nnUNetFrame/nnUNet/nnunet/paths.py
修改如下代码:


base = os.environ['nnUNet_raw_data_base'] if "nnUNet_raw_data_base" in os.environ.keys() else "/root/autodl-tmp/nnUNetFrame/DATASET/nnUNet_raw"
preprocessing_output_dir = os.environ['nnUNet_preprocessed'] if "nnUNet_preprocessed" in os.environ.keys() else "/root/autodl-tmp/nnUNetFrame/DATASET/nnUNet_preprocessed"
network_training_output_dir_base = os.path.join(os.environ['RESULTS_FOLDER']) if "RESULTS_FOLDER" in os.environ.keys() else "/root/autodl-tmp/nnUNetFrame/DATASET/nnUNet_trained_models"

修改后注意保存文件

nnUNetFrame文件夹中新建CREMI_nnUNet文件夹,存放CREMI原始数据
数据下载地址:https://cremi.org/
这里我们只使用非padding数据
点击AutoPanel使用网盘传输

nnUNet实战(一):CREMI挑战赛简单实践
选择相应的网盘,点击右侧下载按钮即可,文件会自动上传至/root/autodl-tmp中
nnUNet实战(一):CREMI挑战赛简单实践
这里只上传非padding部分,如图所示:
nnUNet实战(一):CREMI挑战赛简单实践
之后将文件移入相应的文件夹中,完成。

; 三、简单实践

1.训练

打开CREMI数据处理文件
autodl-tmp/nnUNetFrame/nnUNet/nnunet/dataset_conversion/Task061_CREMI.py
将其中main的base路径进行替换,我这里是90行


    base = "/root/autodl-tmp/nnUNetFrame/CREMI_nnUNet"

然后进行保存。
之后打开命令行,输入指令运行程序,使得原始的hdf数据转换为nnUNet能读取的数据。

python autodl-tmp/nnUNetFrame/nnUNet/nnunet/dataset_conversion/Task061_CREMI.py

nnUNet实战(一):CREMI挑战赛简单实践
数据预处理使用如下命令
nnUNet_plan_and_preprocess -t 61

CREMI任务ID为61,所以参数t为61。这个过程会消耗很多的时间,速度慢的原因在于对要进行插值等各种操作。

nnUNet实战(一):CREMI挑战赛简单实践
开始训练
nnUNet_train 3d_fullres nnUNetTrainerV2 61 4

61代表任务ID,4代表五折交叉验证中的第4折(0代表分成五折后的第一折)。所有的任务都应当在”4″的情况下,也就是五折交叉验证中的第一折数据集下进行。
如果出现训练终端,你要继续训练的情况请在这行命令之后加上:
-c

nnUNet实战(一):CREMI挑战赛简单实践
可以看到已经进行训练。

官方的预训练文件地址:
https://zenodo.org/record/3734294#.XyYR5mMzY5n

2.推理

在autodl-tmp/nnUNetFrame/DATASET/nnUNet_raw/nnUNet_raw_data/Task061_CREMI下创建inferTs文件夹,以存储测试集推理数据
这其中Ts代表测试集合,Ts代表训练集

nnUNet实战(一):CREMI挑战赛简单实践
这里看到测试集数据直接是nii.gz格式,因此不用转换。
nnUNet实战(一):CREMI挑战赛简单实践
nnUNet_predict -i autodl-tmp/nnUNetFrame/DATASET/nnUNet_raw/nnUNet_raw_data/Task061_CREMI/imagesTs/ -o autodl-tmp/nnUNetFrame/DATASET/nnUNet_raw/nnUNet_raw_data/Task061_CREMI/inferTs -t 61 -m 3d_fullres -f 4
   nnUNet_predict:执行预测的命令;
   -i: 输入(待推理测试集);
   -o: 输出(测试集的推理结果);
   -t: 你的任务对应的数字ID;
   -m: 对应的训练时使用的网络架构;
   -f: 数字4代表使用五折交叉验证训练出的模型;
   推理完全部需要消耗相当长的时间,建议先只用一个测试文件进行推理。

nnUNet实战(一):CREMI挑战赛简单实践
nnUNet实战(一):CREMI挑战赛简单实践

最终可能会出现警告

WARNING! Cannot run postprocessing because the postprocessing file is missing. Make sure to run consolidate_folds in the output folder of the model first!

这个问题的解决方案在原github中作者给出了解答
https://github.com/MIC-DKFZ/nnUNet/issues/410

You can run nnUNet_determine_postprocessing to let it figure out what postprocessing (connected component analysis) to use. This does not make a huge difference most of the time, so you can safely omit it.

Best,
Fabian

即运行

nnUNet_determine_postprocessing -t 61 -m 3d_fullres

其中,要保证所有的多折交叉验证全部训练完毕

即运行

nnUNet_train 3d_fullres nnUNetTrainerV2 61 0 -c
nnUNet_train 3d_fullres nnUNetTrainerV2 61 1 -c
nnUNet_train 3d_fullres nnUNetTrainerV2 61 2 -c
nnUNet_train 3d_fullres nnUNetTrainerV2 61 3 -c
nnUNet_train 3d_fullres nnUNetTrainerV2 61 4 -c

根据作者的描述,后处理部分是可选选项,在文件目录中我们也能看到推理文件已经生成

nnUNet实战(一):CREMI挑战赛简单实践
新建文件夹DataPrepare,并切换至该目录,下载相应的CREMI官方处理文件
cd autodl-tmp/DataPrepare
git clone https://github.com/cremi/cremi_python.git

下载完成后进入文件进行编程

新建文件mydata_prepare.py

打开autodl-tmp/nnUNetFrame/nnUNet/nnunet/dataset_conversion/Task061_CREMI.py,使用里面的函数进行nii.gz文件至hdf文件的转换。这里直接写入main函数即可

from collections import OrderedDict

from batchgenerators.utilities.file_and_folder_operations import *
import numpy as np
from nnunet.paths import nnUNet_raw_data, preprocessing_output_dir
import shutil
import SimpleITK as sitk

try:
    import h5py
except ImportError:
    h5py = None

def prepare_submission():
    from cremi.io import CremiFile
    from cremi.Volume import Volume

    base = "/root/autodl-tmp/nnUNetFrame/DATASET/nnUNet_raw/nnUNet_raw_data/Task061_CREMI/inferTs/"

    pred = sitk.GetArrayFromImage(sitk.ReadImage(join(base, "sample_a+.nii.gz"))).astype(np.uint64)
    pred[pred == 0] = 0xffffffffffffffff
    out_a = CremiFile(join(base, 'sample_A+_20160601.hdf'), 'w')
    clefts = Volume(pred, (40., 4., 4.))
    out_a.write_clefts(clefts)
    out_a.close()

    pred = sitk.GetArrayFromImage(sitk.ReadImage(join(base, "sample_b+.nii.gz"))).astype(np.uint64)
    pred[pred == 0] = 0xffffffffffffffff
    out_b = CremiFile(join(base, 'sample_B+_20160601.hdf'), 'w')
    clefts = Volume(pred, (40., 4., 4.))
    out_b.write_clefts(clefts)
    out_b.close()

    pred = sitk.GetArrayFromImage(sitk.ReadImage(join(base, "sample_c+.nii.gz"))).astype(np.uint64)
    pred[pred == 0] = 0xffffffffffffffff
    out_c = CremiFile(join(base, 'sample_C+_20160601.hdf'), 'w')
    clefts = Volume(pred, (40., 4., 4.))
    out_c.write_clefts(clefts)
    out_c.close()

if __name__ == "__main__":
    prepare_submission()
    print("prepare_submission OK")

运行完该py文件

nnUNet实战(一):CREMI挑战赛简单实践
得到结果,完成。
nnUNet实战(一):CREMI挑战赛简单实践
可以看到相关的推理文件已经生成
nnUNet实战(一):CREMI挑战赛简单实践

3.推理结果可视化展示

在/root/autodl-tmp/nnUNetFrame/DATASET/nnUNet_raw/nnUNet_raw_data/Task061_CREMI路径下新建displayTs文件夹,存放推理结果可视化,新建py文件代码如下:

import h5py
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import SimpleITK as sitk

if __name__ =="__main__":

    display_path = "/root/autodl-tmp/nnUNetFrame/DATASET/nnUNet_raw/nnUNet_raw_data/Task061_CREMI/displayTs"
    initial_label_path = "/root/autodl-tmp/nnUNetFrame/DATASET/nnUNet_raw/nnUNet_raw_data/Task061_CREMI/inferTs"
    initial_raw_path = "/root/autodl-tmp/nnUNetFrame/DATASET/nnUNet_raw/nnUNet_raw_data/Task061_CREMI/imagesTs"

    h5pyname = 'sample_C+_20160601'
    if h5pyname[7] == 'A':
        raw_name = 'sample_a+_0000.nii.gz'
    elif h5pyname[7] == 'B':
        raw_name = 'sample_b+_0000.nii.gz'
    elif h5pyname[7] == 'C':
        raw_name = 'sample_c+_0000.nii.gz'
    else:
        raise ValueError

    f_label = h5py.File(os.path.join(initial_label_path, h5pyname + '.hdf'), 'r')
    f_raw = sitk.GetArrayFromImage(sitk.ReadImage(os.path.join(initial_raw_path, raw_name)))

    labels_path = os.path.join(os.path.join(display_path, h5pyname), 'labels')
    raws_path = os.path.join(os.path.join(display_path, h5pyname), 'raws')

    if not os.path.exists(labels_path):

        os.makedirs(labels_path, exist_ok=True)

        print(labels_path, 'created')

    if not os.path.exists(raws_path):

        os.makedirs(raws_path, exist_ok=True)

        print(raws_path, 'created')

    labels_data = f_label['volumes/labels/clefts']
    labels_data_array = labels_data[:]

    labels_data_array[labels_data_array == 0xffffffffffffffff] = 0
    labels_data_array[labels_data_array != 0] = 255
    labels_data_array = labels_data_array.astype(np.uint8)

    for label_index in range(labels_data_array.shape[0]):
        cv2.imwrite(os.path.join(labels_path, r"%05d.png"%label_index), labels_data_array[label_index, :, :], [cv2.IMWRITE_PNG_COMPRESSION, 0])
        print("label " + os.path.join(labels_path, r"%05d.png"%label_index) + ' ok')

    assert labels_data_array.shape == f_raw.shape
    for raw_index in range(f_raw.shape[0]):

        save_img = np.stack([f_raw[raw_index], f_raw[raw_index], f_raw[raw_index]],axis=2)

        save_img[:, :, 0][labels_data_array[raw_index] == 255] = 0
        save_img[:, :, 1][labels_data_array[raw_index] == 255] = 0
        cv2.imwrite(os.path.join(raws_path, r"%05d.png"%raw_index), save_img, [cv2.IMWRITE_PNG_COMPRESSION, 0])
        print("raw " + os.path.join(raws_path, r"%05d.png"%raw_index) + ' ok')

    print('ok')

运行完毕后打开相应的文件夹,可以看到如下效果

nnUNet实战(一):CREMI挑战赛简单实践

四、编程

本人入门期间一直使用pycharm作为开发软件,原因是上手快,debug友好,各种查看方面。但在使用pycharm进行远程开发的时候,它会先将工程文件上传至云服务器中,之后设置文件同步进行修改开发。在使用的过程中可能会出现文件不同步的问题,而且项目中的命令行仍然是本机的命令行,容易与服务器上的命令产生冲突。

这里推荐使用vscode进行远程连接开发。连接方式如下

https://www.autodl.com/docs/vscode/

后续会进行源码的阅读。

Original: https://blog.csdn.net/qq_43264202/article/details/125841823
Author: qq_43264202
Title: nnUNet实战(一):CREMI挑战赛简单实践

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/709985/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球