我是Octave / MATLAB的新手。我想为三角形矢量化一个简单的扫描线填充。这是我要消除的while循环:
#Iterate over all the scan lines from bottom to top
while(yCurr <= 200)
#VARIABLES:
# img - Zero matrix used as an image. Zero is black. Assume 320x200 pixels.
# leftIdx - Vector that contains the left-most pixel to fill in each
# scanline. Dim is 1x200. Each element represents x-coord of a pixel.
# rightIdx - Vector that contains the right-most pixel to fill in each
# scanline. Dim is also 1x200. Each element represents x-coord of a pixel.
# yCurr - The current row being scanned.
#Fill all the pixels in one scan line
img(leftIdx(yCurr) : rightIdx(yCurr), yCurr) = color;
#Increment the row
yCurr++;
endwhile
答案 0 :(得分:2)
简单的解决方案 - 您可以将循环直接更改为一个arrayfun调用。 arrayfun是一种编写循环的奇特方式 - 它为所有提供的参数调用用户定义的函数。需要注意的是,通常与arrayfun一起使用的匿名函数无法分配变量。但是,您可以编写一个普通函数,将颜色分配给img并将其作为参数传递给arrayfun:
function doAllWork(img, rightIdx, leftIdx)
arrayfun(@fill, 1:size(img, 1));
function fill(i)
img(leftIdx(i):rightIdx(i), i) = color;
end
end
我已将fill函数定义为doAllWork中的本地函数,以便它可以访问img,leftIdx,rightIdx。
复杂的解决方案通常在这种情况下,要一次性完成一项任务,你想使用sub2ind来获得矩阵的线性索引(简而言之,在C中,你会写出......就像j一样* NX + i)中。然后你写img(ind)而不是img(indrow,indcol)。问题是每一行在不同的地方都有不同数量的非零。
(复杂)的想法是创建一个显式列索引数组Ii {row} = [leftIdx(row):rightIdx(row)]和相应的行索引数组Ij {row} = [row * ones(1,lenght) (Ii {row}))]用于所有行。没有可以使用arrayfun完成的循环。一旦你有了这个,你可以使用sub2ind在相应的Ii / Ij条目上构建一个线性索引到img中,也可以使用arrayfun来调用。代码看起来像这样
nrows=1:size(img, 1);
Ii=arrayfun(@(i)(leftIdx(i):rightIdx(i)), nrows, 'UniformOutput', false);
Ij=arrayfun(@(i)(i*ones(1,length(Ii{i}))), nrows, 'UniformOutput', false);
lin=arrayfun(@(i)(sub2ind(size(A), Ij{i}, Ii{i})), nrows, 'UniformOutput', false);
img([lin{:}])=color;
这种方法在您的情况下没有多大用处 - 它太复杂了。但它对于arrayfun能做什么很有启发性,而sub2ind的技巧通常非常有用。
答案 1 :(得分:1)
我认为您最初的基于循环的解决方案是最佳解决方案。 为什么呢?
我唯一要改变的是while
- &gt; for
for yCurr = 1:200
img(leftIdx(yCurr) : rightIdx(yCurr), yCurr) = color;
end
答案 2 :(得分:1)
虽然不是OP的主要问题(即如何对光栅扫描进行矢量化),但在MATLAB中用于填充三角形值的简洁解决方案可以来自使用poly2mask
来指定三角形内的区域,使用三角形顶点,并使用逻辑索引来分配值。
% Example values
yCurr = 1:200;
img = zeros(320, 200);
leftIdx = ones(1,200);
rightIdx = 1:200;
color = 1;
% Define polygon vertices and get mask
x = [leftIdx(1) leftIdx(200) rightIdx(1) rightIdx(200)];
y = [1 1 200 200];
bw = poly2mask(x,y,320,200);
% Assign color values
img(bw) = color;
由于poly2mask
最有可能使用某些基础for,
,因此它不是光栅化扫描的矢量化版本。但是,它提供了处理更复杂的多边形区域的好处。