使用 MONAI 加载和保存各种格式的医学图像

news2024/9/23 9:32:02

本教程属于实战,手把手教你加载各种医学图像数据(nii.gz, .dcm, .png等)。并学会查看医学图像数据的元数据(shape, affine, orientation)。学会使用monai全方位了解你的数据,并把它用于之后的深度学习训练。以及学会保存transform处理后的图像以及分割结果。干货很多,动手跟着一起来。

查看本教程前,请自行下载参考代码,边跑代码边看教程,学习效率更高哦

使用默认 image reader 加载 Nifti 图像

monai 根据文件后缀选择默认阅读器:

  • nii、nii.gz -> NibabelReader
  • png、jpg、bmp -> PILReader
  • npz、npy -> NumpyReader
  • 其他 -> ITKReader

开始实验前准备你的 nifti 格式图像,

filename = '/Users/Downloads/WORD-V0.1.0/imagesTr/word_0002.nii.gz'

如果没有,可以下载monai的示例

# download a test image
tempdir = tempfile.mkdtemp()
test_url = "https://github.com/Project-MONAI/MONAI-extra-test-data/releases/download/0.8.1/avg152T1_RL_nifti.nii.gz"
filename = os.path.join(tempdir, "avg152T1_RL_nifti.nii.gz")
monai.apps.download_url(test_url, filepath=filename)

接下来使用LoadImage加载图像

data = LoadImage(image_only=True, ensure_channel_first=True, simple_keys=True)(filename)
print(f"image data shape: {data.shape}")
print(f"meta data: {data.meta.keys()}")

参数解析

  • image_only: 默认为True,只返回图像;if False, 返回的data就是tuple, image=data[0], metadata(元数据)=data[1]
  • ensure_channel_first:默认为False, if True, 会给图像加一个channel,假如图像shape=[512, 512, 64], 加了channel就变成[1, 512, 512, 64]. 这在深度学习训练中基本都是要设为True, 向本教程的目的是加载图像的话,就不必设为True
    其余参数可以在pycharm源代码里查看

接下来,重点解释一下元数据,这是医学图像独有的信息。可以使用data.meta获取所有的元数据。包括

打勾的几个数据就是我平时用的比较多的,比如做图像分割的时候,要保存图像和分割结果,就需要知道affine信息。分割结果命名想同图像命名对应的时候,就需要知道filename_or_obj.

加载进来的3D图像如何展示出来呢?可以使用monai.visualize.matshow3d功能。

data1 = monai.transforms.Orientation("IPL")(data) # (Left, Right), (Posterior, Anterior), (Inferior, Superior).
fig = monai.visualize.matshow3d(volume=data1, 
                                # title='abdomen CT', 
                                figsize=(20,20),
                                frames_per_row=6, 
                                frame_dim=-3,
                                channel_dim=0,
                                every_n=5,
                                vmin=-300, vmax=600,
                                cmap='gray',
                                fill_value=255)

关于matshow3d函数的更多使用技巧,参考这篇文章【添加文章地址】

加载3D DICOM 图像

LoadImage同样支持加载DICOM图像和DICOM文件夹

filenames = ['/Users/Downloads/CBA60D87FAB145C3A9EB31A1C371C07E/0F9B3029D79B4B7DBE18776D284BB713.dcm',
            '/Users/Downloads/CBA60D87FAB145C3A9EB31A1C371C07E/0F9B3029D79B4B7DBE18776D284BB713.dcm']

folder_path = '/Users/Downloads/CBA60D87FAB145C3A9EB31A1C371C07E'

# load single image
# data = LoadImage(image_only=True)(filenames)

# load  DICOM series
data = LoadImage(image_only=True, ensure_channel_first=True)(folder_path)
print(f"image data shape: {data.shape}")

使用data.meta也可以查看元数据

加载 2D PNG图像

# 下载png图像
tempdir = tempfile.mkdtemp()
filename = os.path.join(tempdir, "MONAI-logo_color.png")
monai.apps.download_url("https://monai.io/assets/img/MONAI-logo_color.png", filepath=filename)

data, meta = LoadImage(image_only=False, reader="PILReader", reverse_indexing=False)(filename)
fig = monai.visualize.matshow3d(data, frame_dim=-1)
print(f"image data shape: {data.shape}")
print(f"meta data: {meta}")

保存图像

例如在图像分割中,想保存分割结果或者预处理后的图像。可以使用SaveImage方法。代码以Nifti图像格式为例

假设加载图像并进行了一些transform

# 假设加载图像并进行了一些transform
filenames = '/Users/Downloads/WORD-V0.1.0/imagesTr/word_0002.nii.gz'
transform = Compose(
    [
        LoadImaged(keys="image", image_only=True, ensure_channel_first=True),
        Resized(keys="image", spatial_size=[256, 256, 240])
    ]
)
test_data = {"image": filenames}
result = transform(test_data)
print(f"image data shape:{result['image'].shape}")
print(result["image"].affine)

保存处理后的图像

img = result["image"]
saver = SaveImage(
    output_dir='./output',
    output_ext=".nii.gz",
    output_postfix="trans",
    # output_dtype=np.uint8, # type改变,保存出来的图像变化大,慎重选择type
    resample=False,
    squeeze_end_dims=True,
    writer="NibabelWriter",
)
img = saver(img)

SaveImage将图像(可以是torch tensor或numpy ndarray的形式)和元数据字典保存到文件中。

保存的文件名将为{input_image_name}_{output_postfix}{output_ext},其中input_image_name是从提供的元数据字典中提取的。如果没有提供元数据,将使用从0开始的递增索引作为文件名前缀。

重要参数解析

  • output_ext:输出扩展名
  • output_postfix:输出后缀,默认为trans,如果输出是分割结果,可以设为seg, 最后文件名就是:{input_image_name}_seg.nii.gz
  • resample: 布尔值。if True, 就会重采样到原始图像大小。适用于在transform中对image做了采样后,保存分割结果又重新采样回去。使得分割结果同原始图像一样大小。此操作会利用原始图像元数据信息的spatail_shape以及original_affine.
  • squeeze_end_dims:if True, 去掉为1的维度,比如chanenl维度一般为1,保存的时候【C,H,W,D】-> 【H, W, D】
  • writer: 可以设置为 None,自动根据 output_ext 来选择合适的读写器。也可以是[“NibabelWriter”、“ITKWriter”、“PILWriter”]

当然,你也可以手动指定 metadata, 以及 filename

saver(img, meta_data=img.meta, filename='img_trans.nii.gz')

注意:这个要看版本,1.3版本没有filename

总结:图像的输出非常依赖于元数据(metadata), 对医学图像不是很熟悉的,重点关注本次内容中关于元数据的部分。monai的好处是加载图像后,图像的元数据(image dir, affine, spatial shape等信息全部都保存下来了,只需要img.meta就可以调出来)。

文章持续更新,可以关注微公【医学图像人工智能实战营】获取最新动态,一个关注于医学图像处理领域前沿科技的公众号。坚持以实践为主,手把手带你做项目,打比赛,写论文。凡原创文章皆提供理论讲解,实验代码,实验数据。只有实践才能成长的更快,关注我们,一起学习进步~

我是Tina, 我们下篇博客见~

白天工作晚上写文,呕心沥血

觉得写的不错的话最后,求点赞,评论,收藏。或者一键三连
在这里插入图片描述

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

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

相关文章

最新ChatGPT网站系统源码+详细搭建部署教程+Midjourney绘画AI绘画

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作Ch…

数据版本控制利器LakeFS的介绍,以及其使用方法,与其它工具结合案例

LakeFS介绍 LakeFS 是一个开源的数据湖版本控制系统,可以帮助用户管理和控制数据湖中的数据版本。以下是LakeFS的一些主要用处和功能介绍: 数据版本控制:LakeFS 提供了类似于 Git 的版本控制功能,可以跟踪和管理数据湖中的数据版…

智能合约:3分钟开发ERC20 token(2)

0.前言 上一节我们讲到了开发智能合约的准备工作,以及在线编程平台remix 智能合约(1) 这一节讲解如何开发、发行一个代币,并具备包括代币铸造mint,转账transfer和销毁burn功能,并确保合约拥有者owner的权限…

HEVC 视频扩展安装包,WIN10上看苹果的照片格式

苹果手机照片放电脑上,后缀名称.HEIC,打开居然要下载 HEVC 视频扩展包才能查看,网盘找到一个记录一下,安装后就可以查看苹果手机照片了。 链接:https://pan.baidu.com/s/13ye9_6brXD32jWAjfS47gQ?pwd36k5 提取码&am…

vue结合Cesium加载gltf模型

Cesium支持什么格式? Cesium支持的格式包括:3D模型格式(如COLLADA、gITF、OBJ)、影像格式(如JPEG、PNG、GeoTIFF)、地形格式(如STL、Heightmap)、矢量数据格式(如GeoJSON…

[AutoSar]基础部分 RTE 05 Port的实例化和初始化

目录 关键词平台说明一、端口类型二、端口的实例化2.1 创建application port2.2 实例化 三、初始化 关键词 嵌入式、C语言、autosar、Rte 平台说明 项目ValueOSautosar OSautosar厂商vector芯片厂商TI编程语言C,C编译器HighTec (GCC) 一、端口类型 如下图所示&am…

java 生成一个当前时间的时间搓

开发过程中 用时间搓数值格式存储 会更加精准 那么 我们在一些日常增删查改中就可以用时间搓来记录操作时间 就一行代码 long timestamp System.currentTimeMillis();他就能生成当前时间的时间搓 运行结果如下 然后 我们可以在 http://shijianchuo.wiicha.com/ 上进行转换查…

YOLOv5改进 | 注意力篇 | ACmix注意力与卷积混合的模型(轻量化注意力机制)

一、本文介绍 本文给大家带来的改进机制是ACmix自注意力机制的改进版本,它的核心思想是,传统卷积操作和自注意力模块的大部分计算都可以通过1x1的卷积来实现。ACmix首先使用1x1卷积对输入特征图进行投影,生成一组中间特征,然后根据不同的范式,即自注意力和卷积方式,分别…

【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax类图

【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax概述 【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax快速入门 【大数据进阶第三阶段之Datax学习笔记】阿里云开源离线同步工具Datax类图 【大数据进阶第三阶段之Datax学习笔记】使用…

2024--Django平台开发-Django知识点(四)

1.知识回顾 创建项目&#xff1a;新项目、别人项目、新版版、老版本 项目目录&#xff08;v1.0版本&#xff09; 路由系统 常见路由编写加粗样式 /index/ 函数 /index/<str:v1> 函数 re_path(ryy/(\d{4})-(\d{2})-(\d{2})/, views.yy), re_path(ryy/(?…

2024新年烟花代码完整版

文章目录 前言烟花效果展示使用教程查看源码HTML代码CSS代码JavaScript 新年祝福 前言 在这个充满希望和激动的2024年&#xff0c;新的一年即将拉开帷幕&#xff0c;而数字科技的创新与发展也如火如荼。烟花绚丽多彩的绽放&#xff0c;一直以来都是新年庆典中不可或缺的元素。…

Spring之代理模式

1、概念 1.1 介绍 二十三种设计模式中的一种&#xff0c;属于结构型模式。它的作用就是通过提供一个代理类&#xff0c;让我们在调用目标方法的时候&#xff0c;不再是直接对目标方法进行调用&#xff0c;而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中…

鸿蒙开发基础运用(ArkTS)-健康生活APP

健康生活应用&#xff0c;主要功能包括&#xff1a; 用户可以创建最多6个健康生活任务&#xff08;早起&#xff0c;喝水&#xff0c;吃苹果&#xff0c;每日微笑&#xff0c;刷牙&#xff0c;早睡&#xff09;&#xff0c;并设置任务目标、是否开启提醒、提醒时间、每周任务频…

2024拜年祝福视频AE模板31套

做短视频必备的AE模板非常好看&#xff0c;跨年做个视频非常漂亮&#xff0c;喜欢的赶紧保存吧&#xff01; 链接&#xff1a;https://pan.quark.cn/s/fc1f3db12049

回首2023,厉兵秣马,启航2024

目录 回首风波的20232023&#xff0c;感恩相遇暂停发文发文狂潮感恩有你备战2024学习之余跆拳道比赛做手工diy 学习心路年初学习伊始心路其后学习后来心路 必须看配图说明 未知的2024Flag 回首风波的2023 2023&#xff0c;感恩相遇 还记得&#xff0c;22年末&#xff0c;23年…

Anaconda下载安装与使用

前言 Pandas之所以被称为工具包&#xff0c;原因是Pandas这个工具是由不同的代码模块组成的。每一个代码模块的功能不同&#xff0c;合在一起构成Pandas的丰富功能。其他工具包亦然。 名称描述NumpyNumpy是通用的数值计算工具包&#xff0c;包含大量数学计算函数和矩阵运算函数…

QT应用篇:QT自定义最小化托盘显示和操作

将应用程序最小化到托盘任务栏中,可以使用Qt框架中的QSystemTrayIcon类。该类允许应用程序在关闭窗口后最小化到系统托盘,保持在后台运行,同时可以显示应用程序图标、添加右键菜单功能以及发送消息通知等。通过学习这些技术,能够为自己的Qt应用程序增加更多的交互性和便利性…

3.1 CUDA Thread Organization

在第2章中&#xff0c;数据并行计算&#xff0c;我们学会了编写一个简单的CUDA C程序&#xff0c;该程序启动内核和线程网格&#xff0c;以对一维数组中的元素进行操作。内核指定每个线程执行的C语句。当我们发动如此大规模的执行活动时&#xff0c;我们需要控制这些活动&#…

【书生·浦语大模型实战营02】《轻松玩转书生·浦语大模型趣味Demo》学习笔记

《轻松玩转书生浦语大模型趣味Demo》 教程文档&#xff1a;《轻松玩转书生浦语大模型趣味 Demo文档》 致谢 感谢助教 MINGX 的帮助&#xff5e; 1、InternLM-Chat-7B 智能对话&#xff1a;生成 300 字的小故事 本节中我们将使用InternLM-Chat-7B 模型部署一个智能对话 Dem…

深入了解static关键字的作用和应用--java面向对象学习

Static修饰成员变量 Static是什么 叫静态&#xff0c;可以修饰成员变量&#xff0c;成员方法 成员变量按有无static修饰分俩种&#xff1a; 类变量&#xff1a;有static修饰&#xff0c;属于类&#xff0c;在计算机里只有一份&#xff0c;会被类的全部对…