【问题标题】:Subtracting sub-arrays gives out of memory error in MATLAB在 MATLAB 中减去子数组会导致内存不足错误
【发布时间】:2011-10-29 21:11:45
【问题描述】:

我正在尝试在 MATLAB 中实现一个非常简单的事情。我有一个 4D 数组中的图像序列,格式如下:(framenumber, height, width, RGB)。

我的堆栈很小,它的大小是:99 480 640 3

我想要实现的是检测 n 个连续图像(使用固定相机拍摄的关于移动物体的图像)之间是否存在运动变化。

为此,我最明显的想法是在堆栈中减去不同的图像,并将它们保存在另一个堆栈中。

这是我尝试运行的非常简单的代码:

vec = 1:size(stack,1)-5
dif = uint8(squeeze(abs(stack(vec,:,:,:) - stack(vec+5,:,:,:))));

但是它给了我内存不足的错误。

Error using  - 
Out of memory. Type HELP MEMORY for your options.

如果我不使用挤压(我需要在这里使用挤压吗?)我什至会收到关于内存不足的 Windows 系统错误。

作为后备,我编写了一个 for 循环,这似乎有效,但前提是我使用 uint8 强制转换。如果没有,它会耗尽内存并给出windows系统错误。

for i = 1:size(stack,1)-5   
    dif(i,:,:,:) = uint8(abs(stack(i,:,:,:) - stack(i+5,:,:,:)));
end

此外,处理这个不太大的数据集(只有 99 帧)需要 20 秒。

你能告诉我应该如何编写一个不尝试将所有内容都保存在内存中的函数吗?这个命令应该只需要很少的内存来比较正在比较的 2 个图像,但是 MATLAB 会尝试出于某种原因在内存中执行所有操作。整个数据集的内存应为 91 MB,因此显然不成问题。

另外,你能解释一下我是否需要使用挤压?当我尝试获取单个图像时,

dif = stack(1,:,:,:) - stack(5,:,:,:);

产生一个 4D 数组,而

dif = squeeze(stack(1,:,:,:) - stack(5,:,:,:));

生成图像格式。但是在上面的 for 循环中,无论有没有挤压,它都会产生相同的结果。为什么会这样?

【问题讨论】:

  • 如果您使用double 类型,您的图像堆栈不会那么小:(99*480*640*3)*8 = 729907200 bytes(即每个 4D 矩阵副本需要大约 700MB 的连续内存)
  • 好的,我修改了我的代码以使用 uint8,所以现在它使用更少的内存。但是,为什么矢量化函数会占用这么多内存?
  • 我试图回答你的一些问题,请看我下面的帖子
  • 好的,谢谢,一切都清楚了。

标签: arrays image matlab image-processing


【解决方案1】:

关于 SQUEEZE,stack 是一个 4D 矩阵,所以dif = stack(1,:,:,:) - stack(5,:,:,:); 也是一个 4D 矩阵,但是第一个维度是单例的。因此,当您将结果分配给现有矩阵(带索引)时,元素会按顺序填充,并且任何单一维度都无效。但是,将结果放入一个新的变量中,4D矩阵的形状保持不变...

您应该注意您的数据类型,如果所有值都是 [0,255] 范围内的整数,那么首先将整个图像堆栈转换为 UINT8。正如我在 cmets 中提到的,这样尺寸的 4D 双矩阵将需要大约 700MB 的连续内存。

现在在 for 循环中,您应该预先分配 dif 矩阵:

dif = zeros([99-5 480 640 3],'uint8');
for i = 1:size(stack,1)-5   
    dif(i,:,:,:) = abs( stack(i,:,:,:) - stack(i+5,:,:,:) );
end

最后,尽管矢量化调用可能更快,但它们确实需要更多内存,因为它们试图分配一个所需的全部空间(而不是使用一次只需要空间来保存一个图像的循环)

【讨论】:

  • 谢谢。感谢 uint8 和预分配,与原来的 20 秒相比,它需要 4 秒!
猜你喜欢
  • 2011-05-05
  • 1970-01-01
  • 2011-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-26
  • 2015-06-26
  • 1970-01-01
相关资源
最近更新 更多