MINC/工具/emma/emma-matlab 内存
外观
MATLAB 是一个非常有用的工具,用于分析医学图像数据。不幸的是,它有一个明显的缺点:MATLAB 内存管理很糟糕。内存很容易变得碎片化,没有尝试进行压缩(除了几乎无用的 MATLABpack函数)。对于大型医学图像体积,结果可能是灾难性的,导致巨大的内存使用,性能低下,在极端情况下,操作系统会终止你的 MATLAB 进程。
控制 MATLAB 内存使用有点像变戏法。有一些通用的指导方针可以遵循,但没有适用于所有情况的硬性规定。以下是一些软性规则
- 尽可能重复使用内存。例如,EMMAgetimages函数允许你指定要使用的内存块。通常,这是包含图像的变量,并且应该与要加载的图像的大小相同
PET = getimages(h,8,1:21,PET);
将重复使用分配给矩阵 PET 的内存,并且不会为返回的图像分配新的内存。这消除了与重新加载一组图像相关的碎片化问题。
- 使用 EMMArescale函数将矩阵乘以标量。此函数不分配新的内存,而是使用已经分配给矩阵的内存。例如,MATLAB 指令
PET = PET .* 5;
将导致碎片化,因为矩阵 PET 将被复制。但是,指令
rescale (PET,5);
具有相同的效果,但不会导致碎片化。
- 初始化大型矩阵。当你想通过一系列操作来缓慢地填充矩阵时,这很有用。例如,如果你想在变量中创建一个 128x128 的图像,一行一行地创建Fake_PET,你应该指定
Fake_PET = zeros(128,128);
这将初始化矩阵为正确的大小,并用零填充。然后,当你用你的值填充矩阵时,它不会被复制,并且不会发生内存碎片化。
- 一次使用少量内存。这可能是 *最重要的规则*,并且可以潜在地解决所有内存使用问题。例如,当分析动态研究时,请考虑分解你的分析,以便它可以一次在一行(或几行)上执行,而不是在整个图像上执行。
例如,考虑 [emma1.html 基本 EMMA 图像操作] 教程中介绍的情况:我们想要生成一个集成图像体积。以下代码片段演示了错误的执行方式
h=openimage('/local/matlab/toolbox/emma/examples/yates_19445.mnc'); h2 = newimage('new.mnc',[0 15], ... '/local/matlab/toolbox/emma/examples/yates_19445.mnc'); ftimes = getimageinfo (h,'MidFrameTimes'); img = zeros (16384,1); for j=1:15 PET = getimages(h,j,1:21); img = ntrapz(ftimes,PET')'; putimages(h2,img,j); end; closeimage(h); closeimage(h2);
这种蛮力技术违反了上述几个准则。它在从 MINC 文件加载图像时没有重复使用内存。它转置PET,这会导致PET被复制。然后它转置来自ntrapz的结果,这会导致此结果被复制。
更好的方法是加载一个切片中的图像,逐行获取数据,然后重新组装成最终图像。以下 MATLAB 代码片段具有与上述代码相同的最终结果,但使用更少的内存(大约 4 兆字节)。
h=openimage('/local/matlab/toolbox/emma/examples/yates_19445.mnc'); h2 = newimage('new.mnc',[0 15], ... '/local/matlab/toolbox/emma/examples/yates_19445.mnc'); ftimes = getimageinfo (h,'MidFrameTimes'); img = zeros (16384,1); for j=1:15 PET = getimages(h,j,1:21,PET); for i=1:128:16257; line = PET(i:i 127,:); img (i:i 127) = ntrapz(ftimes, line')'; end; putimages(h2,img,j); end; closeimage(h); closeimage(h2);