我正在尝试学习 MATLAB,遇到的第一个问题是从静态相机和移动物体的图像序列中猜测背景。首先,我只想对一段时间内的像素进行平均值或中位数,所以它是我想将一个函数应用于 4 维数组的其中一行.
我已将 RGB 图像加载到具有以下尺寸的 4 维数组中:
uint8 [ num_images, width, height, RGB ]
这是我编写的函数,其中包含 4 个嵌套循环。我用预分配但仍然非常慢。在 C++ 中,我相信这个函数的运行速度至少可以快 10 倍到 20 倍,而且我认为在 CUDA 上它实际上可以实时运行。在 MATLAB 中,4 个嵌套循环大约需要 20 秒。我的堆栈有 100 张尺寸为 640x480x3 的图像。
function background = calc_background(stack)
tic;
si = size(stack,1);
sy = size(stack,2);
sx = size(stack,3);
sc = size(stack,4);
background = zeros(sy,sx,sc);
A = zeros(si,1);
for x = 1:sx
for y = 1:sy
for c = 1:sc
for i = 1:si
A(i) = stack(i,y,x,c);
end
background(y,x,c) = median(A);
end
end
end
background = uint8(background);
disp(toc);
end
你能告诉我如何使这段代码更快吗?我尝试过以某种方式仅使用索引直接从数组获取数据进行实验,看起来速度要快得多。它完成于3 秒与 20 秒,因此仅通过编写更小的函数即可实现 7 倍的性能差异。
function background = calc_background2(stack)
tic;
% bad code, confusing
% background = uint8(squeeze(median(stack(:, 1:size(stack,2), 1:size(stack,3), 1:3 ))));
% good code (credits: Laurent)
background=uint8((squeeze(median(stack,1)));
disp(toc);
end
所以现在我不明白如果 MATLAB 可以这么快,那么为什么嵌套循环版本这么慢?我没有进行任何动态调整大小,并且 MATLAB 必须在内部运行相同的 4 个嵌套循环。
为什么会发生这种情况?
有没有办法让嵌套循环运行得更快,就像在 C++ 中自然发生的那样?
或者我应该习惯用这种疯狂的一行语句方式对 MATLAB 进行编程以获得最佳性能吗?
Update
谢谢大家的精彩回答,现在我明白了很多。我的原始代码与stack(:, 1:size(stack,2), 1:size(stack,3), 1:3 ))
没有任何意义,它完全一样stack
,我很幸运使用中位数的默认选项,即使用第一维作为其工作范围。
我认为如何写一个高效的问题最好在另一个问题中问,所以我在这里问:
如何在 MATLAB 中编写向量化函数 https://stackoverflow.com/q/7814220/518169