歪絵(anamorfose, anamorfosis)

円錐アナモルフォーズ

円錐アナモルフォーズは,原画を極座標で表すとき偏角を一定の比率で縮小したもので,変換した絵を円錐の側面に貼り付けて円錐の軸方向(無限遠方)から見たとき,元画像となるものです。

プログラム例
元画像を配列に保持しておきます。描画領域の各画素についてその点に移される元の点の座標を求め(逆変換),それに対応する元画像の色を配列から取得して変換先の点の色を決定しています。
120行の定数alphaで円錐の頂角を指定します。

100 OPTION ARITHMETIC NATIVE
120 LET alpha=1/2*PI       ! 円錐の頂角
130 SET COLOR MODE "NATIVE"       ! 24ビットの色(true color)が使えるようにする。
140 GLOAD "zenkouji.jpg"          ! 元画像(BMP,GIF,JPEGが指定可能)
150 ASK PIXEL SIZE (1,0;0,1)a,b   ! 図の縦横の長さ(ピクセル単位)を調べる
160 DIM c(a,b)                    ! 図の大きさに対応する配列要素を用意する。
170 ASK PIXEL ARRAY (0,1) c       ! 図の各点の色情報を配列に格納する。
180 !                               c(1,1)に左上端,c(a,b)に右下端の画素が入る。
190 CLEAR                         ! 図を消去
200 SET bitmap SIZE 801, 801      ! ウィンドウの大きさを変更
210 SET WINDOW -400,400,-400,400  ! 座標系を再設定
220 SET POINT STYLE 1
230 FOR y=-400 TO 400
240    FOR x=-400 TO 400
250       LET r=SQR(x^2+y^2)*SIN(alpha/2)
260       IF r<>0 THEN LET t=ANGLE(x,y)/SIN(alpha/2)
270       IF ABS(t)<=PI THEN
280          LET i=ROUND(1/2 + a/2 + r*COS(t), 0)  ! 左端 1, 右端 a 
290          LET j=ROUND(1/2 + b/2 - r*SIN(t), 0)  ! 上端 1,下端 b
300          IF 1<=i AND i<=a AND 1<=j AND j<=b THEN
310             SET POINT COLOR c(i,j)            
320             PLOT POINTS:x,y
330          END IF
340       END IF 
350    NEXT x
360 NEXT y
370 END


次のプログラムは頂角60°専用です。円錐の切り口を-90°の位置においています。

100 OPTION ARITHMETIC NATIVE
130 SET COLOR MODE "NATIVE"
140 GLOAD "tokeidai.JPG"
150 ASK PIXEL SIZE (1,0;0,1)a,b
160 DIM c(a,b)
170 ASK PIXEL ARRAY (0,1) c
180 ! c(1,1)に左上端,c(a,b)に右下端の画素が入る。
190 CLEAR
200 SET bitmap SIZE 801, 801
210 SET WINDOW -400,400,-400,400
220 SET POINT STYLE 1
230 FOR y=0 TO 400
240    FOR x=-400 TO 400
250       LET r=SQR(x^2+y^2)/2
260       IF r<>0 THEN LET t=ANGLE(x,y)*2-PI/2
280       LET i=ROUND(1/2 + a/2 + r*COS(t), 0)  ! 左端 1, 右端 a 
290       LET j=ROUND(1/2 + b/2 - r*SIN(t), 0)  ! 上端 1,下端 b
300       IF 1<=i AND i<=a AND 1<=j AND j<=b THEN
310          SET POINT COLOR c(i,j)            
320          PLOT POINTS:x,y
330       END IF
350    NEXT x
360 NEXT y
370 END

  
 元画像(1/2倍)              変換後(1/2倍に縮小)

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

円筒アナモルフォーズ

円筒アナモルフォーズは,おおまかにいうと,原画の垂直方向を極座標の動径に,原画の水平方向を極座標の偏角に置き換えて描画したもので,変換した絵を円筒形の鏡に写すと元の絵が現れます。ただし,それぞれを単純に線形で変換したのでは正しい絵になりません。

極座標が(r,θ)の点Pから出た光が半径r0の円筒の側面で反射して,x軸上,原点からdだけ離れた視点に届くものとします。このとき,入射角・反射角をα,入射光が動径OPとなす角をψ,反射光がx軸となす角をφとすると,


2つの三角形に関する内角と外角の関係から,2α=θ+ψ+φ,
正弦定理から,
r:r0:r'=sinα:sinψ:sin(α−ψ)
d:r0:d'=sinα:sinφ:sin(α−φ)
の関係が成立して,
sinψ=(r0/r)sinα
sinφ=(r0/d)sinα
これらの関係を利用して,r,θからφを求めます。
d,rが大きいときはα=θ/2の近似が成立するので,このαからψ,φを求め,このψ,φからαを求めて,再度,ψ,φを計算すればよい近似値が得られるはずです。
次に示すプログラムでは,直前に計算した点のψ,φを近似計算の初期値に利用することで近似計算のための繰り返し回数を低減しています(410〜450行)。
また,r',d'から反射点の鉛直方向の位置が定まります。
なお,θ,r',d'は,プログラムでは,それぞれ,t,rr,ddと記述しています。

プログラム例
元画像の指定は120行です。
視点の高さ,視点から円筒までの距離を170行,180行で指定します。
230行,240行,250行の定数width,height,topは完成画像が収まるように調整して ください。
円筒の半径は220行で設定します。末尾の定数1.00を1より小さくする場合は,下部 マージン(190行のm)を変更しないと画像の一部が欠けます。
虚像は円筒の最前端から円筒の半径のk倍だけ後方にできると仮定しています。この 仮定が実際に成立するのは円筒の最前端から円筒の半径のe倍だけ手前の点に対して のみです。eの値を200行で定めています。kの値はeの値から導かれます(210行)。eの 値は人間の知覚に関係するので,実験的に適切な値を探してください。

100 OPTION ARITHMETIC NATIVE
110 SET COLOR MODE "NATIVE"        
120 GLOAD "tokeidai.JPG"                     ! 元画像
130 ASK PIXEL SIZE (0,0; 1,1) a,b 
140 DIM c(a,b)                     
150 ASK PIXEL ARRAY (0,1) c                  ! 元画像の色情報を配列に取り込む
160 CLEAR    
170 LET h = b * 5                            ! 視点の高さ
180 LET d = h * 1.2                          ! 円筒から視点までの水平距離
190 LET m = 0                                ! 下部マージン(画像の下部に履かせる下駄)
200 LET e=((b+m)/a)*(d/h)*2.0      ! 正しい虚像に写る点の位置(鏡面の前方,半径に対する比率)
210 LET k=1/(2+1/e)              ! 虚像を生成する位置(鏡面の前端から後方,半径に対する比率)                          
220 LET r0 =SQR(1/(2*k-k^2))*(a/2)*1.00      ! 円筒の半径 
230 LET width=1200                           ! 描画域の幅(大きめに確保)
240 LET height=900                           ! 描画域の高さ(大きめに確保)
250 LET top=200                              ! 円柱の中心を置く位置
260 SET BITMAP SIZE width+1,height+1 
270 LET bottom=-height+top    
280 SET WINDOW -width/2, width/2, bottom , top   
290 DRAW grid(100,100)  
300 DRAW circle WITH SCALE(r0)   ! 円筒
305 PLOT POINTS: 0, -r0*(1*e)    ! 正しい虚像に写る点   
310 LET d2=d-r0+r0*k                              ! 虚像面までの距離 
320 SET POINT STYLE 1   
330 FOR x=-width/2 TO width/2 
340    LET phi=0
350    LET psi=0
360    FOR y=bottom TO top
370       LET r=SQR(x^2+y^2)                     ! 描画する点の絶対値
380       IF r>r0 THEN
390          LET t=ANGLE(x,y) +PI/2                
400          IF t>PI THEN LET t=t-2*PI           ! 描画する点の偏角(-π〜π)下向きが0
410          FOR i=1 TO 2
420             LET alpha=(t+psi+phi)/2  
430             LET phi=ASIN(r0*SIN(alpha)/d) 
440             LET psi=ASIN(r0*SIN(alpha)/r)
450          NEXT i
460          IF ABS(alpha)<=PI/2 THEN
470             WHEN EXCEPTION IN 
480                LET rr=r*SIN(alpha-psi)/SIN(alpha)
490                LET dd=d*SIN(alpha-phi)/SIN(alpha)
500             USE
510                LET rr=r-r0
520                LET dd=d-r0
530             END WHEN
540             LET y0=h/(1+dd/rr)
550             LET x0=d2*TAN(phi)                       ! 元画像のx座標
560             LET y0=h-d2*(h-y0)/(d-r0*COS(alpha-phi)) ! 元画像のy座標
570             LET i=ROUND(x0+ (a+1)/2,0)               ! x0に対応する配列添字
580             LET j=b-ROUND(y0-m)                      ! y0に対応する配列添字
590             IF i>0 AND i<=a AND j>0 AND j<=b THEN
600                SET POINT COLOR c(i,j)
610                PLOT POINTS : x,y  
620             END IF
630          END if
640       END if
650    NEXT y
660 NEXT x
670 END

元画像(1/4倍)




変換後(1/4倍)

変換後の図は,260行を
260 SET BITMAP SIZE width/4+1,height/4+1
に変え,290行,320行のFOR文に STEP 4 を追加して描いたものです。

使い方
完成した歪絵は,MS-Wordなどに貼り付け,円筒の大きさが実際に用いる円筒鏡と同じになるように拡大・縮小して印刷してください。


戻る