nnUnet 大模型学习笔记(续):3d_fullres 模型的推理、切片推理、计算dice系数

news2024/11/26 15:48:21

目录

1. 前言

2. 更改epochs

3. 推理

3.1 nnUNet_predict

3.2 切成小的nii gz文件推理

切片代码

融合代码

3.3 可视化展示

3.4 评估指标

参考


1. 前言

训练了一天半,终于跑完了。。。。

训练的模型在这可以免费下载:

基于nnUnet3d-fullres训练的spineCT训练结果资源-CSDN文库

关于nnUnet的环境搭建、数据集制作、训练网络参考:

第四章:nnUnet大模型之环境配置、数据集制作_nnunet代码详解pytorch-CSDN博客

nnUnet 大模型学习笔记(续):训练网络(3d_fullres)以及数据集标签的处理-CSDN博客

训练过程如下:

生成的结果在 nnUnet_trained_models 目录下:

训练过程的指标可以看曲线图或者训练日志(validation_raw/summary.json):

这里validation_raw/summary.json没有生成,不知道因为什么原因,程序被kill了。。。。

2. 更改epochs

1000个epoch太多了,可以更改官方的参数,如果按照本文的环境搭建,参数在这里

*/environments/nnunet/lib/python3.8/site-packages/nnunet/training/network_training/

3. 推理

nnUnet 是没有推理和测试放在一起的,它会对指定的数据进行推理

如果你有推理的labels的话,那么就可以进行指标计算,这样就可以测试

如果没有labels,那么只有推理

3.1 nnUNet_predict

在最初的数据集里,新建inferTs,用于推理nnUnet推理的结果,把想要推理的数据放在imagesTs下就行了

好像这里的测试数据必须得是0000.nii.gz结尾的,是因为多模态?

运行下面的命令

nnUNet_predict -i DATASET/nnUNet_raw/nnUNet_raw_data/Task01_Spine/imagesTs/ -o DATASET/nnUNet_raw/nnUNet_raw_data/Task01_Spine/inferTs/ -t 1 -m 3d_fullres -f 0
  •  -i 是想要预测的数据目录 ,一般为imagesTs
  • -o 是保存推理后的数据目录,一般为inferTs
  • -t 是任务的训练标号
  • -m 是nnUnet训练好的模型
  • -f 是训练m模型的几折交叉验证

由于是直接使用模型进行推理, inference done. 后出现 WARNING! Cannot run postprocessing because the postprocessing file is missing. 也即表示已经完成推理。

若CT层数太多或层间距小,可能会卡在 inference done. 阶段,此时需要将CT切分成几部分分别进行 推理。

这里有时候nnUnet推理不出来,可能是因为输入层数太多?参考3.2 处理

3.2 切成小的nii gz文件推理

如果3.1可以成功推理,可以不参考这步!!!

切片代码

注意,这里只需要把想要推理的数据进行切片,然后推理完再拼接即可!!

代码如下:

import SimpleITK as sitk
import numpy as np
import os
import cv2


# 切片函数
def sliceMain(rt):
    img = sitk.ReadImage(rt)
    img_array = sitk.GetArrayFromImage(img)  # nii-->array

    print('input size:', img_array.shape)

    channel = img_array.shape[0]
    y, z = channel // 100, channel % 100  # 2 91

    if z == 0:
        n = y
        print('切出的nii.gz文件个数:', n)
    else:
        n = y + 1
        print('切出的nii.gz文件个数:', n)

    for i in range(n):
        star, end = i * 100, i * 100 + 100 

        if i == n - 1:  # 最后一个切片
            img_select = img_array[star:, :, :]
            shape = img_select.shape
            img_select = sitk.GetImageFromArray(img_select)

            img_save_name = 'data_' + str(i) + '_0000.nii.gz'
            print(img_save_name, 'channel:', shape)
            sitk.WriteImage(img_select, img_save_name)

        else:
            img_select = img_array[star:end, :, :]
            shape = img_select.shape
            img_select = sitk.GetImageFromArray(img_select)

            img_save_name = 'data_' + str(i) + '_0000.nii.gz'
            print(img_save_name, 'channel:', shape)
            sitk.WriteImage(img_select, img_save_name)


if __name__ == '__main__':
    root = 'spine_001.nii.gz'

    # 切片函数
    sliceMain(rt=root)

切片结果:

效果如下:

然后推理就行了!

nnUNet_predict -i DATASET/nnUNet_raw/nnUNet_raw_data/Task01_Spine/imagesTs/ -o DATASET/nnUNet_raw/nnUNet_raw_data/Task01_Spine/inferTs/ -t 1 -m 3d_fullres -f 0

融合代码

推理完成的nii数据下放在data目录下,然后运行下面代码会自动拼接:

import SimpleITK as sitk
import numpy as np
import os
import cv2


# 切片函数
def sliceMain():
    data = [os.path.join('data',u) for u in os.listdir('data')]

    ret_nii = None
    for index,i in enumerate(data):
        img = sitk.ReadImage(i)
        img_array = sitk.GetArrayFromImage(img)  # nii-->array
        print(i,':',img_array.shape)

        if index ==0:
            ret_nii = img_array
        else:
            ret_nii = np.concatenate((ret_nii,img_array),axis=0)

    print('返回的数组size:',ret_nii.shape)
    sitk.WriteImage(sitk.GetImageFromArray(ret_nii),'ret.nii.gz')


if __name__ == '__main__':
    # 切片函数
    sliceMain()

效果如下:

左上角是拼接后的,其余三个是nnUNet推理生成的

3.3 可视化展示

下面是原图加真实gt

下面是原图加nnUNet推理结果:

3.4 评估指标

在labelsTs下放入对应的标签即可

如果评估的话,需要真实的gt图!!!

import numpy as np
import SimpleITK as sitk
from tqdm import tqdm


def main(pred, gt,n):
    gt = sitk.GetArrayFromImage(sitk.ReadImage(gt))             # [ 0  2  3  4  5  6  7  8  9 10 11 12 13 14 15]
    pred = sitk.GetArrayFromImage(sitk.ReadImage(pred))

    dice = []
    for h in tqdm(range(n)):
        if h == 0:
            continue

        g = np.zeros(gt.shape,dtype=np.uint8)           # 单独提取某个灰度级
        g[gt == h] = 255
        g[g<255] = 0
        g[g==255] = 1

        p = np.zeros(pred.shape,dtype=np.uint8)         # 单独提取某个灰度级
        p[pred == h] = 255
        p[p<255] = 0
        p[p==255] = 1

        if len(np.unique(p)) == 1 or len(np.unique(g)) == 1:
            dice.append('None')

        else:
            dice_score = (2*(p*g).sum() / ((p+g).sum()+1e-8))
            dice.append(round(dice_score,4))

    print(dice)

    for i in range(len(dice) - 1,-1,-1):
        if dice[i] == 'None':
            dice.remove('None')

    print('mean dice',np.array(dice).mean())


if __name__ == "__main__":

    gt_path = 'labels.nii.gz'
    pred_path = 'infer.nii.gz'
    classes = 19

    main(pred=pred_path,gt=gt_path,n=classes)

指标如下:

['None', 0.4523, 0.9311, 0.967, 0.9732, 0.9756, 0.9687, 0.9665, 0.9674, 0.9787, 0.9743, 0.9802, 0.9811, 0.9826, 0.974, 'None', 'None', 'None']
mean dice 0.9337642857142857

代码主要实现思路:

因为推理的时候,不是所有的数据同时包含所有标签,所以这里为了方便评估,将所有的类别全部显示。如果没有某个标签就设定为None,然后计算平均dice的时候,就会去掉相应的空标签。

这是nnUnet某个epoch计算的平均dice指标

参考

参考博文如下:nnUNet使用指南(一):Ubuntu系统下使用nnUNet对自己的多模态MR数据集训练 - 梅雨明夏 - 博客园

nnUNet训练并推理自己的数据集_nnunet训练自己数据集-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2219699.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深⼊理解指针(2)

目录 1. 数组名的理解 2. 使⽤指针访问数组 3. ⼀维数组传参的本质 4. ⼆级指针 5. 指针数组 6. 指针数组模拟⼆维数组 1. 数组名的理解 我们在使⽤指针访问数组的内容时&#xff0c;有这样的代码&#xff1a; int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[…

rancher安装并快速部署k8s 管理集群工具

主机准备 准备4台主机 3台用于k8s集群 &#xff0c;1台用于rancher 每台服务器新增配置文件 vi etc/sysctl.confnet.ipv4.ip_forward 1 刷新生效 sysctl –p 安装docker 安装的时候可以去github上检索rancher看看最新版本适配那个版本的docker&#xff0c;这里安装23.0.1…

Linux 线程概念及线程控制

1.线程与进程的关系 执行流&#xff08;Execution Flow&#xff09;通常指的是程序执行过程中的控制路径&#xff0c;它描述了程序从开始到结束的指令执行顺序。例如我们要有两个执行流来分别进行加法和减法的运算&#xff0c;我们可以通过使用 fork 函数来创建子进程&#xf…

智慧商城项目2-登录模块

登录页静态布局 1.先重置默认样式 找到styles/common.less文件,没有就新建 // 重置默认样式 * {margin: 0;padding: 0;box-sizing: border-box;}// 文字溢出省略号.text-ellipsis-2 {overflow: hidden;-webkit-line-clamp: 2;text-overflow: ellipsis;display: -webkit-box;-…

CentOS7安装RabbitMQ-3.13.7、修改端口号

本文安装版本&#xff1a; Erlang&#xff1a;26.0 官网下载地址 Erlang RabbitMQ&#xff1a;3.13.7 官网下载地址 RabbitMQ RabbitMQ和Erlang对应关系查看&#xff1a;https://www.rabbitmq.com/which-erlang.html 注&#xff1a;安装erlang之前先安装下依赖文件&#xff0…

无人机之放电速率篇

无人机的放电速率是指电池在一定时间内放出其储存电能的能力&#xff0c;这一参数对无人机的飞行时间、性能以及安全性都有重要影响。 一、放电速率的表示方法 放电速率通常用C数来表示。C数越大&#xff0c;表示放电速率越快。例如&#xff0c;一个2C的电池可以在1/2小时内放…

《知道做到》

整体看内容的信息密度较低。绿灯思维、积极心态、反复练习值得借鉴。 引言 行动是老子&#xff0c;知识是儿子&#xff0c;创造是孙子&#xff01;行是知之始&#xff0c;知是行之成。 前言 工作中最让你失望的事情是什么&#xff1f; 一个人行为的改变总是先从内心想法的转…

MySQL 【日期】函数大全(六)

目录 1、TIME_FORMAT() 按照指定的格式格式化时间。 2、TIME_TO_SEC() 将指定的时间值转为秒数。 3、TIMEDIFF() 返回两个时间之间的差值。 4、TIMESTAMP() 累加所有参数并将结果作为日期时间值返回。 5、TIMESTAMPADD() 将指定的时间间隔加到一个日期时间值上并返回结果。…

数据库->库的操作

目录 一、查看数据库 1.显示所有的数据库 二、创建数据库 1.创建数据库 2.查看警告信息 3.创建一个名为database的数据库 三、字符集编码和校验(排序)规则 1.查看数据库⽀持的字符集编码 2.查看数据库⽀持的排序规则 3.一条完整创建库的语句 4. 不同的字串集与排序规…

keepalived(高可用)+nginx(负载均衡)+web

环境 注意&#xff1a; (1) 做高可用负载均衡至少需要四台服务器&#xff1a;两台独立的高可用负载均衡器&#xff0c;两台web服务器做集群 (2) vip&#xff08;虚拟ip&#xff09;不能和物理ip冲突 (3) vip&#xff08;虚拟ip&#xff09;最好设置成和内网ip同一网段&#xf…

传感器驱动系列之PAW3212DB鼠标光电传感器

目录 一、PAW3212DB鼠标光电传感器简介 1.1 主要特点 1.2 引脚定义 1.3 传感器组装 1.4 应用场景 1.5 传感器使用注意 1.5.1 供电选择 1.5.2 SPI读写设置 1.5.3 MOTION引脚 1.6 寄存器说明 1.6.1 Product_ID1寄存器 1.6.2 MOTION_Status寄存器 1.6.3 Delta_X寄存器…

【论文笔记】X-Former: Unifying Contrastive and Reconstruction Learning for MLLMs

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: X-Former: Unifying Contr…

为您的 WordPress 网站打造完美广告布局 A5广告单元格插件

一个为 WordPress 网站量身定制的强大工具,它将彻底改变您展示广告的方式 灵活多变的布局设计 A5 广告单元格插件的核心优势在于其无与伦比的灵活性。无论您是想要创建整齐的网格布局,还是希望打造独特的不规则设计,这款插件都能满足您的需求。 自定义网格数量&#xff1a;从 2…

C# 条形码、二维码标签打印程序

1、条码标答打印主界面 2、打印设置 3、生成QR代码 private void GetBarcode_T(string lr) { QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();//创建一个对象 qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE; //设置编码测量…

Mamba学习笔记(2)—序列数据处理基础

文章目录 (1) RNN&#xff08;Recurrent Neural Networks&#xff09;基本原理代码定义 (2) SLTM (Long Short-Term Memory)基本原理代码定义 (3) GRU (Gated Recurrent Unit)基本原理代码定义 (4) Transformer&#xff08;☆☆☆Attention Is All You Need☆☆☆&#xff09;0…

量子门电路开销——T门、clifford门、toffoli门、fredkin门

在量子计算中&#xff0c;T门的成本比Clifford门高出很多倍的原因与量子计算中纠错的实现、物理门操作的复杂性以及容错量子计算架构中的成本评估有关。以下是几个关键原因&#xff0c;解释了为什么 T 门的成本在量子计算中远远高于 Clifford 门&#xff1a; 1. T 门和 Cliffo…

递归、搜索与回溯(二)——递归练习与快速幂

文章目录 递归、搜索与回溯——递归两两交换链表中的节点Pow(x, n) 递归、搜索与回溯——递归 该文仍然是解决递归问题&#xff0c;值得注意的是快速幂算法。接下来会系统学习二叉树深搜题目&#xff0c;慢慢走向搜索与回溯。 两两交换链表中的节点 原题链接&#xff1a;24. 两…

AI识谱——将乐曲转化为五线谱

导言&#xff1a; 会乐曲的小伙伴在听到一首好听的乐曲的时候&#xff0c;肯定想过将这首歌曲转换为谱子给弹出来。除了上网找乐谱、请大神帮忙扒谱或者自己扒谱外&#xff0c;小伙伴也可以尝试一下本文介绍的AI识谱流程&#xff0c;让我们开始吧&#xff01; 注意了&#xf…

2024 Python3.10 系统入门+进阶(十七):面向对象基础

目录 一、面向对象概述1.1 面向对象简介1.2 对象和类1.3 定义属性和行为1.3.1 用数据描述对象的状态1.3.2 行为就是动作 1.4 隐藏细节并创建公共接口1.5 组合1.6 继承1.6.1 继承提供抽象1.6.2 多重继承 二、封装2.1 Python类定义2.2 创建类的成员2.2.1 创建实例方法并访问2.2.2…

PythonExcel批量pingIP地址

问题&#xff1a; 作为一个电气工程师&#xff08;PLC&#xff09;&#xff0c;当设备掉线的时候&#xff0c;需要用ping工具来检查网线物理层是否可靠连接&#xff0c;当项目体量过大时&#xff0c;就不能一个手动输入命令了。 解决方案一&#xff1a; 使用CMD命令 for /L %…