2次元の図形要素を2値画像データとして描画
2次元の図形要素を2値画像データとして描画する Octave のプログラム例を示す.
前準備
Octave のインストールが済んでいること.
必見 Web ページ: http://www.csse.uwa.edu.au/~pk/Research/MatlabFns/
必見 Web ページ: http://www.eecs.berkeley.edu/Research/Projects/CS/vision/bsds/
* プロンプトを変えたいときは,次のように操作する.
PS1('> ')
* Octave のインストールによっては,Octave の起動時に毎回次の操作を行う必要があるかもしれない
pkg load image
プログラムのソースコード
function A = intersect_X ( px, vx, val ) # 点 (px,py) を通過するベクトル(xv,vy) が x = val と交わる交点について. # px + A * vx = val となるような A を求める if ( abs( vx ) < 0.0001 ) A = NaN; else A = (val - px) / vx; endif endfunction function A = intersect_Y ( py, vy, val ) # 点 (px,py) を通過するベクトル(xv,vy) が y = val と交わる交点について. # py + A * vy = val となるような A を求める if ( abs( vy ) < 0.0001 ) A = NaN; else A = (val - py) / vy ; endif endfunction function AA = intersect_rectangle ( px, py, vx, vy, width, height ) # 点 (px,py) を通過するベクトル(xv,vy) がなす軌跡 (px,py) + A * (xv,vy) と # 左上 (1,1), 右下 (width, height) である長方形と交点(2つ)について,その交点における A の値を求める # 4 本の直線との交点 a1 = intersect_X( px, vx, 1 ); a2 = intersect_X( px, vx, width ); a3 = intersect_Y( py, vy, 1 ); a4 = intersect_Y( py, vy, height ); A = [a1 a2 a3 a4]; # a1, a2, a3, a4 の中で正であり、最小のもの e1 = min( A( find( A > 0 ) ) ); # a1, a2, a3, a4 の中で負であり、最大のもの e2 = max( A( find( A < 0 ) ) ); AA = [e1 e2]; endfunction function mask = draw_linesegment ( x1, y1, x2, y2, width, height ) # 2端点を指定しての線分の描画 # 左上 (1,1), 右下 (width, height) である画像に,線分 (x1, y1) - (x2, y2) を描く mask = poly2mask([x1 x2 x1], [y1 y2 y1], height, width); endfunction function mask = draw_linesegment_vectorform ( px, py, vx, vy, width, height ) # 左上 (1,1), 右下 (width, height) である画像に,(px, py) を通過し,方向が (vx, vy) であるような線分を書く AA = intersect_rectangle( px, py, vx, vy, width, height ); mask = draw_linesegment( px + (vx * AA(1)), py + (vy * AA(1)), px + (vx * AA(2)), py + (vy * AA(2)), width, height ); endfunction function mask = draw_vector ( px, py, vx, vy, width, height ) # 左上 (1,1), 右下 (width, height) である画像に,線分 (x1, y1) - (x2, y2) を描く # (px, py) + (vx, vy) が画像からはみ出るか? AA = intersect_rectangle( px, py, vx, vy, width, height ); if ( AA(1) > 1 ) # はみ出ない mask = draw_linesegment( px, py, px + vx, py + vy, width, height ); else mask = draw_linesegment( px, py, px + ( vx * AA(1) ), py + ( vy * AA(1) ), width, height ); endif endfunction px = 140; py = 250; vx = 8; vy = -12; width = 512; height = 512; # 線分 mask = draw_linesegment_vectorform(px, py, vx, vy, width, height); imshow( mask ); w = input("please press Enter to proceed"); # ベクトル mask2 = draw_vector( px, py, vx, vy, width, height ); imshow( mask2 ); w = input("please press Enter to proceed");
実行方法と実行結果の例
- (オプション)Cygwin からリモートログインする場合
startx xhost + ssh -X username@ipaddress
- ソースコードをファイルとして保存
- Octave を起動
- Octave の source コマンドを使って実行
cd <ソースコードのファイルを置いたディレクトリ> source "<ソースコードのファイル名>"
- 実行が終わるまで数秒待つ
- 途中で何回か「please press Enter to proceed」と表示されるので,Enter キーを押す.
使用方法の説明
ここでのプログラムは,2値画像データ(2 次元の配列)に,2次元の図形要素を描画するもの.gnuplot と混同しないように.
- 直線の描画(2端点の指定)
mask = draw_linesegment(100, 100, 400, 200, 640, 480); imshow( mask );
- 直線の描画(通過点とベクトルの指定)
実行例
mask = draw_linesegment_vectorform(320, 240, 1, 0.5, 640, 480); imshow( mask );
- ベクトルの描画
mask = draw_vector(100, 200, 30, 40, 640, 480); imshow( mask );
ブレゼンハム(Bresenham)のアルゴリズム
ブレゼンハム(Bresenham)のアルゴリズムとは,整数演算で,ビットマップ上に線分を描画するアルゴリズム.
(x1, y1), (x2, y2) 間の線分を書く. x1, y1, x2, y2 は整数とする場合で、 Octave のプログラムは次の通り
x1 = 95; y1 = 80; x2 = 100; y2 = 100; dx = x2 - x1; dy = y2 - y1; if ( abs(dx) > abs(dy) ) i = x1; j = y1; di = sign(dx); c = floor( dx / 2 ); while( ( i * di ) <= ( x2 * di ) ) printf("%d %d\n", i, j) i = i + di; c = c + dy; if ( abs(c) > abs(dx) ) j = j + sign(dy); c = c - ( sign(dx) * sign(dy) * dx ); endif endwhile else i = x1; j = y1; dj = sign(dy); c = floor( dy / 2 ); while( ( j * dj ) <= ( y2 * dj ) ) printf("%d %d\n", i, j) j = j + dj; c = c + dx; if ( abs(c) > abs(dy) ) i = i + sign(dx); c = c - ( sign(dx) * sign(dy) * dy ); endif endwhile endif