行列と幾何変換 III

本資料では、同次座標系と変換の合成を紹介します。余裕がある方は独自で資料を読んでコードを試してみてください。 質問がある場合、担当教員に聞いてください。

復習

「家」の描画は繰り返し使用されますので、関数でまとめて定義しましょう。

In [1]:
def myhome():
    import matplotlib.pyplot as plt
    import numpy as np
    p_list = np.array([[-3,2],[-2,2],[-2,0],[2,0],[2,2],[3,2],[0,3],[-3,2]]).T

    plt.plot(p_list[0,:],p_list[1,:],'-r')

    plt.grid()
    g = plt.subplot()
    g.set_aspect('equal')
    plt.show()

myhomeを使って、家を描いてみます。

In [3]:
myhome()

1. 同次座標系

平面上の点$(x,y)$を以下のように拡張して、同次座標系で表現することができます。

$$ \left(\begin{array}{c}x\\y\end{array}\right) \Rightarrow \left(\begin{array}{c}x\\y\\1 \end{array}\right) $$

同次座標系から普通の座標系までの変換($c\not =0$のとき):

$$ \quad (x,y,c) \rightarrow (\frac{x}{c},\frac{y}{c})$$

同次座標系を使って、アフィン変換は行列とベクトルの積に書けます。

例えば、アフィン変換 $$ \left(\begin{array}{c}x\\y\end{array}\right) \Rightarrow \left(\begin{array}{c}x'\\y'\end{array}\right) = \left(\begin{array}{cc}a&b\\ c& d\end{array}\right) \left(\begin{array}{c}x\\y\end{array}\right) + \left(\begin{array}{c}x_0 \\ y_0 \end{array}\right) $$

に対して、同次座標系を使うと、アフィン変換を一つの行列にまとめることができます。

$$ \left(\begin{array}{c}x\\y\\1 \end{array}\right) \Rightarrow \left(\begin{array}{c}x'\\y'\\1 \end{array}\right) =\left(\begin{array}{ccc}a&b&x_0\\ c&d & y_0 \\ 0 & 0 & 1 \end{array}\right) \left(\begin{array}{c}x\\y\\1 \end{array}\right) $$

回転変換は以下のようになります。 $$ A = \left(\begin{array}{ccc}\cos \alpha & -\sin \alpha & 0\\ \sin\alpha & \cos \alpha & 0 \\0 & 0 & 1 \end{array}\right) $$

$(x_0,y_0)$方向への平行移動は以下のようになります。

$$ A = \left(\begin{array}{ccc} 1 & 0 & x_0 \\ 0 & 1 & y_0\\ 0 & 0 & 1 \end{array}\right) $$

例1

以下の例は「家」を反時計周り$\alpha=30$度回転して、ベクトル(5,1)で移動します。

変換行列: $$ A = \left(\begin{array}{ccc}\cos \alpha & -\sin \alpha & 5\\ \sin\alpha & \cos \alpha & 1 \\0 & 0 & 1 \end{array}\right) $$

In [21]:
#同次座標系でかかれている点列
import matplotlib.pyplot as plt
import numpy as np
import math

def myhome_affine(A):

    p_list = np.array([[-3,2,1],[-2,2,1],[-2,0,1], [2,0,1], [2,2,1],  [3,2,1], [0,3,1], [-3,2,1]]).T
    plt.plot(p_list[0,:],p_list[1,:],'-r')

    #変換行列を同次座標系に現れる点にかける
    new_p_list = A@p_list

    plt.plot( new_p_list[0,:] / new_p_list[2,:], new_p_list[1,:] / new_p_list[2,:] ,'-b')
    plt.axes().set_aspect('equal')
    plt.grid()
    
#同次座標系における変換行列
alpha=30/180*math.pi;
A=[[math.cos(alpha), -math.sin(alpha), 5],  
   [math.sin(alpha), math.cos(alpha),1],
   [0, 0, 1]]

myhome_affine(A)

演習 1

授業で作成した家に対して、同次座標の形に直してみてください。ここで、変換行列は$3 \times 3$の行列であることを注意しなさい。

In [23]:
#演習1
def myhome_affine(A):
    pass
    # Input parameter A:
    # A: 3*3 matrix

2. 合成変換

同次座標系を使う場合、合成変換は行列の積の形に書けます。例えば、平面上の点に作用する2つの変換について、それぞれの変換に対応する行列を$A_1$と$A_2$とします。 この場合、2つの変換の合成に対応する行列$A$は次のようになります。

  • $A_1$の後に$A_2$を作用する場合、$A=A_2A_1$。
  • $A_2$の後に$A_1$を作用する場合、$A=A_1A_2$。

演習2

家を$(2,3)$方向へ移動する変換$A_1$と反時計周り$\alpha = 10$度回転する変換$A_2$を考えます。

$$ A_1 = \left(\begin{array}{ccc} 1 & 0 & 2 \\ 0 & 1 & 3\\ 0 & 0 & 1 \end{array}\right), \quad A_2 = \left(\begin{array}{ccc}\cos \alpha & -\sin \alpha & 0\\ \sin\alpha & \cos \alpha & 0 \\0 & 0 & 1 \end{array}\right)\:. $$

行列$B_1=A_1A_2$と$B_2=A_2A_1$をそれぞれ家にかけて、変換結果の違いを確認してください。

In [19]:
# 演習2のコード