射影変換

DRAW文による図形変形

A=(aij)を
DIM A(4,4)
により定義された4行4列の行列(A(i,j)=aij)とするとき,絵定義pict_aを
DRAW pict_a WITH A
で描くと, 点( x,y )を行列演算




( x' y' z' w' ) = ( x y 0 1 )
(
a11 a12 a13 a14
a21 a22 a23 a24
a31 a32 a33 a34
a41 a42 a43 a44
)

により定まる点(x'/w', y'/w')に対応させる図形変形が行われる。
この変形は射影変換である。
 

例1

視点の高さを1.5mとして,10m先の地平面に描かれた図形がその地点で垂直に描かれているように見えるようにしたい。
10m先に垂直に立つ平面上の座標を(x,y),10m先から地平面に座標(x',y')を考える。ただし,xの正の向きを水平方向,yの正の向きを鉛直方向,x'の正の向きをxの正の向きと同じ,y'の正の向きを視点から遠ざかる方向とする。
このとき,10+y':y'=1.5:y となるので,

y'=   10y  
1.5−y

また,x:x'=10:10+y' となるので,上の結果も利用して,

x'=   1.5x    
1.5−y


したがって,この変換は,



A =
(
1.5  0  0      0
0    10  0 -1
0  0     0  0
0  0  0 1.5
)

が定める射影変換である。

この変換は,次のようなプログラムで実行できる。

(1)図形を変換して描く

100 SET WINDOW -20,20,0,40 
110 DRAW grid0                           ! 1升=1m×1m
120 DIM m(4,4)                           ! 変換を行列で指定する。 
130 DATA 1.5,  0,  0,   0
140 DATA   0, 10,  0,  -1
150 DATA   0,  0,  0,   0
160 DATA   0,  0,  0, 1.5    
170 MAT READ m                          
180 DRAW HalfHouse WITH m               ! 行列を用いて変換して描く 
190 PICTURE HalfHouse
200    DRAW house WITH SCALE(0.5)
210 END  PICTURE
220 PICTURE House   
230    SET AREA COLOR 15                           
240    PLOT AREA:  0,1; 0,0; 2,0; 2,1                        ! 壁     
250    SET AREA COLOR 2                   
260    PLOT AREA: -0.6,1; 2.6,1; 2,2; 0,2                    ! 屋根             
270    SET AREA COLOR 10
280    PLOT AREA: 0.1,0; 0.1,0.8; 0.5,0.8; 0.5,0             ! ドア              
290    SET AREA COLOR 5
300    PLOT AREA: 1.4,0.4; 1.9,0.4; 1.9,0.8; 1.4,0.8         ! 窓 
310    SET AREA COLOR 12
320    PLOT AREA: 1.7,2; 1.7,2.3; 1.5,2.3; 1.5,2             ! 煙突
330 END PICTURE
340 END


(2)画像を変換する
ここでは,文字を画像として扱い,変換対象としている。
なお,このプログラムにはVer. 7.4.2以降が必要。

100 SET WINDOW -10,10,0,20   
110 DRAW grid0                      ! 1升=1m×1m
120 DIM m(4,4)                      ! 変換を行列で指定する。 
130 DATA 1.5,  0,  0,   0
140 DATA   0, 10,  0,  -1
150 DATA   0,  0,  0,   0
160 DATA   0,  0,  0, 1.5    
170 MAT READ m                          
180 DRAW pict1 WITH m               ! 行列を用いて変換して描く 
190 PICTURE pict1
200    SET TEXT HEIGHT 0.8               
210    PLOT TEXT ,AT -1,0:"東京"    ! 変換対象画像として文字を描く
220 END PICTURE
230 END

バージョンが古い場合は,次のプログラムを用いる。

100 SET COLOR MODE "NATIVE" !24ビットの色が使えるようにする
110 SET bitmap SIZE 801,801 
120 SET WINDOW -2,2,0,4               
130 DIM p(400,200)    !縦1m,横2mの範囲を取り込める大きさの配列
140 SET TEXT HEIGHT 0.8               
150 SET TEXT FONT "MS 明朝",0
160 PLOT TEXT ,AT -1,0:"東京"      ! 変換対象画像として文字を描く
170 ASK PIXEL ARRAY (-1,1) p 
180 CLEAR
190 SET WINDOW -10,10,0,20          ! 座標系を再設定
200 DIM m(4,4)                      ! 変換を行列で指定する。 
210 DATA 1.5,  0,  0,   0
220 DATA   0, 10,  0,  -1
230 DATA   0,  0,  0,   0
240 DATA   0,  0,  0, 1.5    
250 MAT READ m
260 DRAW pict1 WITH m               ! 行列を用いて変換して描く 
270 DRAW grid0                      ! 1升=1m×1m
280 PICTURE pict1
290    MAT PLOT CELLS, IN  -1, 1 ; 1  , 0 : p
300 END PICTURE
310 END 



例2

遠方を眺めると遠方ほど小さく見える。これは,例1と逆の関係である。
視点の高さを1.5mとして,0.5m先に地平面に垂直に置かれたスクリーンに見えたとおりに写しとったとするとき,原点をスクリーン中央の地平面との接点に置くと,地平面上の点(x,y)は,次式で定まるスクリーン上の点(x',y')に写る。

y'=  1.5y    (1.5/0.5)y  
0.5+y 1+y/0.5
x'=  0.5x     x   
0.5+y 1+y/0.5

したがって,この変換(x, y)→(x', y')は,



A =
(
0.5  0  0      0
0    1.5  0  1
0  0     0  0
0  0  0 1.5
)

が定める射影変換である。

この変換は,次のようなプログラムで実行できる。
なお,このプログラムの実行にはVer.7.4.2以降が必要。

100 DIM a(4,4)
110 DATA 0.5,   0,  0,   0
120 DATA   0, 1.5,  0,   1
130 DATA   0,   0,  0,   0
140 DATA   0,   0,  0, 0.5
150 MAT READ a
160 SET WINDOW -1,1,0,2             
170 DRAW grid0                      ! 1升=1m×1m
180 DRAW pict1 WITH a               ! 行列を用いて変換して描く 
190 PICTURE pict1
200    SET TEXT HEIGHT 0.8               
210    PLOT TEXT ,AT -1,0:"東京"       ! 変換対象画像として文字を描く
220 END PICTURE
230 END

バージョンが古い場合は,次のプログラムを用いる。

100 SET COLOR MODE "NATIVE"         ! 24ビットの色(true color)が使えるようにする
110 SET bitmap SIZE 801,801 
120 SET WINDOW -2,2,0,4               
130 DIM p(400,200)                  ! 縦1m,横2mの範囲を取り込める大きさの配列
140 SET TEXT HEIGHT 0.8               
150 SET TEXT FONT "MS 明朝",0
160 PLOT TEXT ,AT -1,0:"東京"       ! 変換対象画像として文字を描く
170 ASK PIXEL ARRAY (-1,1) p 
180 CLEAR
190 DIM m(4,4)                      ! 変換を行列で指定する。 
200 DATA 0.5,   0,  0,   0
210 DATA   0, 1.5,  0,   1
220 DATA   0,   0,  0,   0
230 DATA   0,   0,  0, 0.5
240 MAT READ m
250 DRAW pict1 WITH m               ! 行列を用いて変換して描く 
260 DRAW grid0                      ! 1升=1m×1m
270 PICTURE pict1
280    MAT PLOT CELLS, IN  -1, 1 ; 1  , 0 : p
290 END PICTURE
300 END 


地平面に格子を描いてみると,この変換の性質がさらによく見えてくる。

100 SET WINDOW -1,1,0,2    
110 DIM m(4,4)                      ! 変換を行列で指定する。 
120 DATA 0.5,   0,  0,   0
130 DATA   0, 1.5,  0,   1
140 DATA   0,   0,  0,   0
150 DATA   0,   0,  0, 0.5
160 MAT READ m
170     DRAW pict1 WITH m               ! 行列を用いて変換して描く 
180     PICTURE pict1
190        FOR y=0 TO 10
200           PLOT LINES:-100,y; 100,y
210        NEXT y
220        FOR x=-5 TO 5
230           PLOT LINES:x,0;x,1000
240        NEXT x
250     END PICTURE
260  END 


次のプログラムは格子を斜め45度と-45度に描いている。

100 SET WINDOW -1,1,0,2         
110 DIM m(4,4)                      ! 変換を行列で指定する。 
120 DATA 0.5,   0,  0,   0
130 DATA   0, 1.5,  0,   1
140 DATA   0,   0,  0,   0
150 DATA   0,   0,  0, 0.5
160 MAT READ m
170 DRAW pict1 WITH m               ! 行列を用いて変換して描く 
180 PICTURE pict1
190    FOR x=-10 TO 10
200       PLOT LINES:x,0; 50+x,50
210    NEXT x
220    FOR x=-10 TO 10
230       PLOT LINES:x,0;-50+x,50
240    NEXT x
250 END PICTURE
260 END 


例3

垂直な壁面を仰角θで見上げるように撮影した写真画像を仰角なしで撮影したように修正することを考える。
図のA点から仰角θで撮影された写真画像は,図の太線に存在したかのように写る。ただし,この図は真横から見た図である。
写真画像で水平面をx軸とし,縦方向をy軸とする座標を考える。また,本来の壁面にも同様に水平との交線をx軸,垂直方向をy軸とする座標を考える。
仮想的な画像面上の点P(x,y)の座標から本来の点P'(x',y')の座標を求めるための変換式を作成したい。

y座標は,真横から見た図を利用して,AO=dとおくと,
y':y cosθ=OP':QP=AO:AQ=d:d−y sinθ=1:1−y(sinθ/d) より

y'=   y cosθ   
1−y (sinθ/d)


x座標は,真上から見た図を用いて,
x':x=AO:AQ=d:d−y sinθから,

x'=     x     
1−y (sinθ/d)


したがって,この変換は,



A =
(
1  0  1      0
0    cosθ   0 -(sinθ)/d
0  1     0  0
0  0  0  1
)

が定める射影変換である。


dは,垂直方向の画角の半分をα(=∠BAH),画像の高さをb(=BC)とすると,
AH tanα=b/2,d cosθ=AH より

d= b   1    
2  cosθ tanα

と求まる。
さらに,OH=cとすると,c=d sinθ 。


この変換は,次のようなプログラムで実行できる。
元画像の横幅をa,高さをbとして,水平線がx軸となるように座標系を設定している。

100 OPTION ARITHMETIC NATIVE
110 OPTION ANGLE DEGREES
120 LET t=16                      ! 仰角
130 LET v=33                      ! 垂直方向画角の半分
140 SET COLOR MODE "NATIVE"         ! 24ビットの色(true color)が使えるようにする。
150 GLOAD "tokeidai.JPG" 
160 ASK PIXEL SIZE (0,0; 1,1) a,b   ! 図の縦横の長さ(ピクセル単位)を調べる
170 DIM p(a,b)                      ! 図の大きさに対応する配列要素を用意する。
180 ASK PIXEL ARRAY (0,1) p         ! 図の各点の色情報を配列に格納する。
190 SET BITMAP SIZE 401,401         ! ウィンドウの大きさを変更
200 CLEAR                           ! 図を消去
210 SET WINDOW -200, 200, -90, 310    ! 座標系を再設定
220 DRAW grid(100,100)                ! 座標軸を描く  
230 LET d=b/2/TAN(v)/COS(t)
240 LET c=d*SIN(t) 
250 DIM m(4,4)                        ! 変換を行列で指定する。 
260 MAT m=IDN
270 LET m(2,2)=COS(t)
280 LET m(2,4)=-SIN(t)/d
290 DRAW pict1 WITH m                 ! 行列を用いて変換して描く 
300 PICTURE pict1
310    MAT PLOT CELLS, IN  -a/2 + 1, c+b/2 ; a/2  , c-b/2 + 1 : p
320 END PICTURE
330 END 

 
  元画像(札幌時計台)                    変換後

謝辞 元画像は,こちらからいただきました。


戻る