You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NiFTI格式MRI图像批量加载出现WinError 8存储不足问题求助

解决大量NIfTI图像加载时的内存不足问题

首先得明确:你用img.uncache()没效果的核心原因——真正占内存的是你存在img_arr里的img_data数组,uncache()只是清除nibabel加载对象内部的临时缓存,对已经提取出来并存在列表里的numpy数组完全无效。1500张MRI的体积加起来远超你的52GB内存,自然会触发内存不足错误。

下面是几个针对性的解决方案,按实用性排序:

1. 分批处理+内存主动回收

不要一次性把所有图像加载到内存,而是分成小批次处理,每处理完一批就主动释放内存。这是最直接有效的方案:

import nibabel as nib
import gc
import numpy as np

# 设置每批处理的图像数量,根据你的内存调整,比如50张
batch_size = 50
total_files = len(datadir)

for batch_start in range(0, total_files, batch_size):
    batch_end = min(batch_start + batch_size, total_files)
    current_batch = datadir[batch_start:batch_end]
    
    # 临时存储当前批次的图像数据
    temp_img_arr = []
    for file_path in current_batch:
        img = nib.load(file_path)
        # 转换为float32减少内存占用(比默认float64省一半)
        img_data = img.get_fdata(dtype=np.float32)
        temp_img_arr.append(img_data)
        img.uncache()
        
        # 在这里完成单张图像的预处理/特征提取等操作
        # process_single_image(img_data)
    
    # 处理完整个批次后,清空临时列表并强制回收内存
    del temp_img_arr
    gc.collect()

2. 使用内存映射(Memory Mapping)

nibabel的img.dataobj是内存映射对象,不会一次性把整个图像加载到内存,只有当你访问具体区域时才会读取对应的数据。这种方式几乎不占内存,但要注意:加载后的文件不能被移动或删除,访问速度会稍慢一点。

import nibabel as nib

# 存储内存映射对象,而不是完整数组
img_mmap_arr = []
for file_path in datadir:
    img = nib.load(file_path)
    # 直接使用dataobj,不要用get_fdata()
    mmap_data = img.dataobj
    img_mmap_arr.append(mmap_data)

# 处理时只加载需要的部分,比如读取某个切片
for mmap_data in img_mmap_arr:
    # 只把当前切片加载到内存
    slice_data = mmap_data[:, :, 100]
    # process_slice(slice_data)

3. 使用生成器逐个加载处理

用生成器代替列表,每次只加载一张图像,处理完就释放内存,完全避免批量存储的内存压力:

import nibabel as nib
import gc
import numpy as np

def nifti_loader(file_paths):
    for path in file_paths:
        img = nib.load(path)
        # 可选:转换为更节省内存的数据类型
        img_data = img.get_fdata(dtype=np.float32)
        yield img_data
        
        # 主动释放当前图像的内存
        img.uncache()
        del img, img_data
        gc.collect()

# 遍历生成器,逐个处理图像
for img_data in nifti_loader(datadir):
    # 完成你的处理逻辑
    # process_image(img_data)
    pass

4. 降低数据精度减少内存占用

如果你的处理流程允许,把图像数据从默认的float64转换为float32(内存占用减半),或者如果图像是整数类型(比如原始MRI的uint16数据),直接用对应类型加载:

# 转换为float32
img_data = img.get_fdata(dtype=np.float32)

# 如果是整数格式的图像,直接用uint16加载(内存只有float64的1/4)
img_data = np.asarray(img.dataobj, dtype=np.uint16)

这些方案可以组合使用,比如「生成器+数据类型转换」,能最大程度压缩内存占用,适配你的硬件配置完成1500张图像的处理。

内容的提问来源于stack exchange,提问作者Mira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:12:58