2

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
4

3 に答える 3

2

簡単な解決策-ループを直接1つの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

img、leftIdx、rightIdxにアクセスできるように、塗りつぶし関数をdoAllWorkのローカル関数として定義しました。

複雑な解決策通常、このような場合、一度に割り当てを行うには、sub2indを使用して、行列に線形インデックスを取得します(つまり、Cではj * nx + iのようにsthと記述します)。次に、img(indrow、indcol)の代わりにimg(ind)と記述します。問題は、すべての行の場所によって非ゼロの数が異なることです。

(複雑な)アイデアは、明示的な列インデックス配列Ii {row} = [leftIdx(row):rightIdx(row)]および対応する行インデックス配列Ij {row} = [row * ones(1、lenght(Ii {行}))]すべての行。arrayfunを使用して実行できるループなし。これを取得したら、対応するIi / Ijエントリでsub2indを使用して、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を使用したトリックは一般的に非常に便利です。

于 2012-09-18T19:45:05.693 に答える
1

オリジナルのループベースのソリューションが最良のソリューションだと思います。なんで?

  1. プロファイリングを実行しない限り、ベクトル化されたソリューションが実際に高速であるかどうかを知ることができないためです。
  2. forループを使用するコードは、読者にとって明確だからです。コードは4行しかなく、見ればその目的がわかります。

私が変更する唯一のものはwhile->for

for yCurr = 1:200
    img(leftIdx(yCurr) : rightIdx(yCurr), yCurr) = color;
 end
于 2012-09-18T20:49:25.470 に答える
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,、ラスター化スキャンのベクトル化バージョンではありません。ただし、より複雑なポリゴン領域を処理できるという利点があります。

于 2012-09-18T21:39:28.013 に答える