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
相关产品推荐
相关产品推荐

