行列と幾何変換

今日の授業内容:

  • アフィン変換
  • 同次座標系

復習

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

In [1]:
function myhome()

p_list = [-3,2;-2,2; -2,0; 2,0; 2,2;  3,2; 0,3; -3,2]';

plot(p_list(1,:), p_list(2,:),'-b')

grid on
axis("equal")

end

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

In [2]:
myhome()
Gnuplot Produced by GNUPLOT 5.0 patchlevel 3 -0.5 0 0.5 1 1.5 2 2.5 3 3.5 -3 -2 -1 0 1 2 3 gnuplot_plot_1a

演習 1

  • 前回の授業で考えた「家」を描くためのmyhome()関数を作ってください。
In [ ]:
function myhome()
%ここにコードを描いてください。
end

1. アフィン変換

アフィン変換は線形変換(拡大や縮小,回転など)と平行移動を組み合わせた変換です. 一般的なアフィン変換は以下の形にかけます。

$$ \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) $$

ここで、$(x_0,y_0)$は平行移動の方向を示しています。

行列Aとベクトルbで変形された家の描画関数 myhome_affine を作ります。

In [6]:
function myhome_affine(A,b)
% Input parameters
% A: 2*2 matrix
% b: 2*1 matrix

p_list = [-3,2;-2,2; -2,0; 2,0; 2,2;  3,2; 0,3; -3,2]';
n=size(p_list,2);  % point numbers.

new_p_list = A*p_list + b;
plot(new_p_list(1,:), new_p_list(2,:),'-b')

grid on
axis("equal")

end
In [7]:
alpha=pi/6;
A=[cos(alpha), -sin(alpha);  sin(alpha), cos(alpha)]
b=[0;0]
A =

   0.86603  -0.50000
   0.50000   0.86603

b =

   0
   0

In [8]:
myhome_affine(A,b)
Gnuplot Produced by GNUPLOT 5.0 patchlevel 3 -1 -0.5 0 0.5 1 1.5 2 2.5 3 -3 -2 -1 0 1 gnuplot_plot_1a

演習 2

各自で設計した家にアフィン変換をかける関数 myhome_affine(A,b)を作りなさい。

In [10]:
function myhome_affine(A,b)
%ここにコードを描いてください。
end

演習 3

注意:[1]と[2]をmyhome_affine()で描いてください。

  • [1] 家を反時計回り45度回転し、$x$方向で$2$、$y$方向で$3$移動して、描いてください。
  • [2] 家を$(2,3)$方向で移動し、反時計回り45度回転して、描いてください。
  • [3] アフィン変換は線形変換でしょうか?
  • [4] 平行移動と回転の順番が変わると、得られた図は同じでしょうか?

ヒント:回転変換をA、平行移動を$(x_0,y_0)=(2, 3)$とすると、

[1]のアフィン変換は

$$ \left(\begin{array}{c}x\\y\end{array}\right) \Rightarrow \left(\begin{array}{c}x'\\y'\end{array}\right) = A \left(\begin{array}{c}x\\y\end{array}\right) + \left(\begin{array}{c}x_0 \\ y_0 \end{array}\right) $$

[2]のアフィン変換は

$$ \left(\begin{array}{c}x\\y\end{array}\right) \Rightarrow \left(\begin{array}{c}x'\\y'\end{array}\right) = A \left( \left(\begin{array}{c}x\\y\end{array}\right) + \left(\begin{array}{c}x_0 \\ y_0 \end{array}\right) \right) = A \left(\begin{array}{c}x\\y\end{array}\right) + A \left(\begin{array}{c}x_0 \\ y_0 \end{array}\right) $$

2. 同次座標系

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

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

同次座標系から普通の座標系までの変換:

$$(x,y,c) \rightarrow (x/c,y/c)$$

同次座標系を使って、アフィン変換は行列とベクトルの積に書けます。 $$ \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) $$

以下の例は「家」を反時計周り30ど回転して、(2,3)方向へ移動します。この場合、 $$ A = \left(\begin{array}{ccc}\cos \alpha & -\sin \alpha & 3\\ \sin\alpha & \cos \alpha & 2 \\0 & 0 & 1 \end{array}\right) $$

In [1]:
%同次座標系でかかれている点列
p_list = [-3,2,1;-2,2,1; -2,0,1; 2,0,1; 2,2,1;  3,2,1; 0,3,1; -3,2,1]';

p_list

hold on
plot(p_list(1,:),p_list(2,:),'-r')

alpha=30/180*pi;
A=[cos(alpha), -sin(alpha), 2;  sin(alpha), cos(alpha),3 ; 0, 0,1];

new_p_list = A*p_list;

new_p_list

plot( new_p_list(1,:) ./ new_p_list(3,:), new_p_list(2,:) ./ new_p_list(3,:) ,'-b')

grid on
axis("equal")
p_list =

  -3  -2  -2   2   2   3   0  -3
   2   2   0   0   2   2   3   2
   1   1   1   1   1   1   1   1

new_p_list =

 Columns 1 through 7:

  -1.59808  -0.73205   0.26795   3.73205   2.73205   3.59808   0.50000
   3.23205   3.73205   2.00000   4.00000   5.73205   6.23205   5.59808
   1.00000   1.00000   1.00000   1.00000   1.00000   1.00000   1.00000

 Column 8:

  -1.59808
   3.23205
   1.00000

Gnuplot Produced by GNUPLOT 5.0 patchlevel 3 0 1 2 3 4 5 6 -3 -2 -1 0 1 2 3 4 gnuplot_plot_1a gnuplot_plot_2a

演習 4

  • myhome_affineを修正して、以下のような関数を作りなさい。ここで、変換行列は$3 \times 3$の行列であることを注意しなさい。
In [33]:
function myhome_affine_2(A)
% Input parameters
% A: 3*3 matrix

% ここにコードを描いてください。

end

3. 合成変換

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

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

例、家を$(2,3)$方向へ移動する変換$A_1$と反時計周り$\alpha$度を回転する変換$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$の違いを確認してください。

以下の行列に対応する変形を考えてください。分からない場合、上記のセルのコードで試してください。

$$ A = \left(\begin{array}{ccc} 1 & 0 & 0 \\ 0 & 1 & 0\\ 0 & 0 & 1/2 \end{array}\right) $$
  • $x$方向$2$倍、$y$方向$2$倍に伸ばすという変形対応する$3\times 3$行列を求めてください。
  • このような行列は一つのみでしょうか?

演習 5

以下のリンクで書かれた「坂の上の家」のように様々な形を持っている家を描いてください。

家に関する変形や、家の数は自由です。

変形の例:家を(-10,5)に移動して、反時計周り10度で回転し、家の高さを1.5倍にすること。

In [ ]:

演習 7 (チャレンジ)

ここで考えているのはカメラの撮影に関わる3次元空間のアフィン変換です。

三次元空間の点$(x,y,z)$を 平面$z=1$への投影変換を考えます。

  • 点$(x,y,z)$を$z=1$への投影を$(x',y')$とします。$(x',y')$の計算式を求めてください。

三次元空間の点を同次座標系で考えます。3次元の点を$X=(x,y,z,1)$で書きます。$X$の投影した点$X'$は2次元同次座標系で$X'=(x,y,z)$と書けます。

  • $X$から$X'$まで変換させる行列$P$を求めてください。
  • 頂点が$(-1,-1,5)$,$(1,0,5)$,$(0,2,5)$,$(0,0,6)$である四面体の平面$z=1$への投影を描いてください。
In [ ]: