如何优化图像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...
矩阵包含 0
和 1
,我们可以 element-wise 将它们乘以 A
和 B
以过滤掉 [=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 是重复次数,我们假设 A
和 B
是沿 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
的最后一个线性索引处。具体来说,请注意 I
的 shape 是无关紧要的,因为它无论如何都会以线性索引方式进行解释。
换句话说,I
的逻辑索引与I(:)
的逻辑索引相同,[I,I,I]
的逻辑索引与[=21=的逻辑索引相同].
并且如果 I
的大小为 A(:,:,1)
,则 [I,I,I]
的大小为 A(:,:,:)
,这样在线性索引意义上它可以用作有效的逻辑将 I
的每个线性索引与 A
.
的等效线性索引相匹配的索引
我想知道是否有一种可索引的方式在 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...
矩阵包含 0
和 1
,我们可以 element-wise 将它们乘以 A
和 B
以过滤掉 [=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 是重复次数,我们假设 A
和 B
是沿 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
的最后一个线性索引处。具体来说,请注意 I
的 shape 是无关紧要的,因为它无论如何都会以线性索引方式进行解释。
换句话说,I
的逻辑索引与I(:)
的逻辑索引相同,[I,I,I]
的逻辑索引与[=21=的逻辑索引相同].
并且如果 I
的大小为 A(:,:,1)
,则 [I,I,I]
的大小为 A(:,:,:)
,这样在线性索引意义上它可以用作有效的逻辑将 I
的每个线性索引与 A
.