如何优化图像for循环中的条件语句?

How to optimize conditional statement in for loop over image?

我想知道是否有一种可索引的方式在 Octave 上执行以下代码,因为它是迭代的,因此与使用索引相比确实很慢。

for i = [1:size(A, 1)]
  for j = [1:size(A, 2)]
    if (max(A(i, j, :)) == 0)
      A(i, j, :) = B(i, j, :);
    endif
  endfor
endfor

A​​ 和 B 是两个重叠的 RGB 图像,如果 A(i,j) 在所有三个通道上都为 0,我希望 A(i,j) 具有 B(i,j) 值。这种形式的速度很慢,但我对这种语言的实验还不够多,无法对其进行矢量化。

max() function可以取单个矩阵和return沿维度的最大值

还有 all() function that tells you if all values along a dimension are nonzero, and the any() function 会告诉您维度上的 任何 值是否非零

A = reshape(1:75, 5, 5, 3)
A(2, 3, :) = 0;
B = ones(size(A)) * 1000

use_pixel_from_A = any(A, 3)
use_pixel_from_B = ~use_pixel_from_A

现在对于第 3 轴的每个元素,您知道从 A 中获取哪些像素以及从 B 中获取哪些像素。由于我们的 use_pixel... 矩阵包含 01,我们可以 element-wise 将它们乘以 AB 以过滤掉 [=15] 的元素=] 和 B 根据需要。

C = zeros(size(A));
for kk = 1:size(A, 3)
    C(:, :, kk) = A(:, :, kk) .* use_pixel_from_A + B(:, :, kk) .* use_pixel_from_B
end

您的代码可以向量化如下:

I = max(A,[],3) == 0;
I = repmat(I,1,1,3);
A(I) = B(I);

第一行是你的 max conditional statement within the loop, but vectorized across all of A. This returns a 2D array, which we cannot directly use to index into the 3D arrays A and B, so we apply repmat 的直接副本,以沿第 3 个维度复制它(这里的 3 是重复次数,我们假设 AB 是沿 3 维具有 3 个元素的 RGB 图像)。最后,索引赋值将相关值从 B 复制到 A.

要将其推广到任何数组大小,请将 repmat 语句中的“3”替换为 size(A,3)

这里没有添加太多内容,但也许这会让您更好地理解,因此值得添加另一个解决方案。

% example data
  A = randi( 255, [2,4,3] ); A(2,2,:) = [0,0,0];
  B = randi( 255, [2,4,3] );

% Logical array with size [Dim1, Dim2], such that Dim3 is 'squashed' into a 
% single logical value at each position, indicating whether the third dimension
% at that position does 'not' have 'any' true (i.e. nonzero) values.
  I = ~any(A, 3);

% Use this to index A and B for assignment.
  A([I,I,I]) = B([I,I,I])

这种方法可能比 repmat 方法更有效,repmat 是一种稍微昂贵的操作,但可能不太容易理解其工作原理。 但是。了解它的工作原理可以教会你一些关于 matlab/octave 的知识,所以这是一个很好的学习点。

Matlab 和 Octave 在 column major order 中存储数组(相对于 Python)。这也是做 A(:) 将 return A 作为向量,在 column-by-column 基础上构建的原因。这也是您可以使用单个索引(称为“线性索引”)对 3 维数组进行索引的原因,当您计算向下列的元素数量时,该索引将对应于您到达的元素。

执行逻辑索引时,matlab/octave 有效地采用逻辑向量,将该向量的每个线性索引与 A 的等效线性索引相匹配,并决定是否 return 它或不是,基于该线性索引处的逻辑索引的布尔值是真还是假。如果您提供的逻辑数组 I 的大小小于 A,则索引将简单地停止在 I 的最后一个线性索引处。具体来说,请注意 Ishape 是无关紧要的,因为它无论如何都会以线性索引方式进行解释。

换句话说,I的逻辑索引与I(:)的逻辑索引相同,[I,I,I]的逻辑索引与[=21=的逻辑索引相同].

并且如果 I 的大小为 A(:,:,1),则 [I,I,I] 的大小为 A(:,:,:),这样在线性索引意义上它可以用作有效的逻辑将 I 的每个线性索引与 A.

的等效线性索引相匹配的索引