2012/08/18

文系のための「内積」(2)

さて、行列の「掛け算」の基本的な話は済んだ。
では、「掛け算」を使うとどのようなことができるのか、
Rを使って、色々と見ていくことにする。

ここからは、多少、複雑になってくる。
自信の無い人は、Rコンソールを立ち上げて、
実際に確認しながら読んだ方が良い。読むだけだと、逆に混乱する。

今回は、図形の変換という点から見てみる。
Rコンソールを立ち上げ、以下のデータを準備する。
最初に、以下のコマンドを貼り付ける。実行はまだ

# 「足し算」の例で用いたデータの読み込み
# Windows & Linux の人は以下のコマンド
X <- as.matrix(read.table("clipboard", sep = ","))

# Mac の人は以下のコマンド
X <- as.matrix(read.table(pipe("pbpaste"), sep = ","))

以下をコピーして、貼りつけた上記のコマンドを実行
最終列に、「1」が並んでいるのは、計算の都合上のもの。
数学の魔法をかけるための準備。魔法にも準備が必要。

x,y,dummy
P1,0,0,1
P2,40,40,1
P3,40,0,1
P4,0,0,1

同様に、以下のコマンドをコピーして貼り付け。実行はまだ

T <- as.matrix(read.table("clipboard", sep = ","))

以下のデータをコピーしてから上記コマンドを実行

1,0,10
0,1,15
0,0,1

以前は、「足し算」を使って、図形の並行移動を行った。
これは、「掛け算」を使ってもできる。どういうことか?

二回目に貼り付けたデータ「Tが、変換行列になっている。
以下の行列の中で、TxとTy という変数が確認できる。
Tx の変数がx軸の移動量であり、Ty がy軸方向の移動量である。
本当にそのように都合良い行列があるのか?ふむ、ある。



手計算の場合には、少々、厄介に見えるかもしれないが、
とにかく、以下のようになる。


行列の「掛け算」では、掛けられる方を横に、
掛ける方を縦に掛け算し、足し合わせるのだった。
したがって、途中の計算は、以下のようになり、



したがって、


計算ミスをしそうだ。実際、計算ミスはよくする。
数学が苦手な人間の多くは、計算ミスによるコンプレックス
心配無用。手計算でできる事の方が少ない
だから、思い切って計算機の力を借りることにする。

R上では、以下のように計算する。

t(T %*% t(X))

そして、Xには図形データの行列が、Aには変換行列が入っている。
t()関数というのは、転置(Transpose)のことだった。

注意する点は、「掛け算」の仕方。
計算機では、一般的にアスタリスク(「*」)が「掛け算の記号」であるが、
Rの「行列の掛け算」では「%*%」とする。これが、行列の掛け算の記号である。

以上を理解した上で、このコマンドを観察してみると、
なるほど、上記の数式と同じことは誰でも理解できる。
実行すると、以下のようになる。

> t(T %*% t(X))
   [,1] [,2] [,3]
P1   10   15    1
P2   50   55    1
P3   50   15    1
P4   10   15    1

一応、重ねあわせを行なってみる。方法は、以下の通り。
plot(X, type="b", col = "blue", xlim = c(0,60), ylim = c(0, 60))
par(new=TRUE)
plot(t(T%*%t(X)), type="b",col = "red", xlim = c(0,60), ylim = c(0, 60))

行列の「掛け算」を使うと、大きさを変えることもできる。
これを、「スケーリング」と呼ぶ。これをやってみる。
平行移動と同様に、次のような変換行列を用意する。
Sx というのが、xの値のスケールなり、
Sy というのが、yの値のスケールとなる。
平行移動と同様に、この変換行列で都合よく変換できる。



では、さっそくやってみる。まずは、以下の命令後をコピーして貼り付け。

# Windows と Linux の人は以下のコマンド。
S <- as.matrix(read.table("clipboard", sep = ","))

# Mac の人は、以下のコマンド
S <- as.matrix(read.table(pipe("pbpaste"), sep = ","))

以下のデータをコピーしてから上記コマンドを実行
この例では、x軸とy軸の両方に二倍比率を変えても構わない

2,0,0
0,2,0
0,0,1

ここまでの復習も兼ねて、手計算にも挑戦すると良い。
回答は、Rの計算結果が示してくれる。



Rでの実行結果は以下の通り。以下の通りになっているかを確認。

> t(S%*%t(X))
   [,1] [,2] [,3]
P1    0    0    1
P2   80   80    1
P3   80    0    1
P4    0    0    1

さらに、プロットして、確認してみる。
plot(X, type="b", col = "blue", xlim = c(0,90), ylim = c(0, 90))
par(new=TRUE)
plot(t(S%*%t(X)), type="b",col = "red", xlim = c(0,90), ylim = c(0, 90))

最後に、「回転」もやってみよう。これも「掛け算」でできる。
ここで準備する変換行列は次の通り。



ここでは、三角関数が出てくる。ここでは、詳しいことは書かない。
とは言え、全く知らない人も居るかもしれない。基本だけ。

角度には、二種類が存在する。
1つ目は、いわゆる「度(Degree)」で、
2つ目は、「弧度(Radian)」というもの。
この2つくらいは知っておかなくてはならない。

弧度」というのは、聞きなれないかもしれないが、
要するに、半径の長さと弧の長さが等しくなる角度を1とした単位である。
数的な処理では、「」よりも「弧度」を使うことが良くある。

とにかく、次の式は記憶。記憶できなければ、いつでも参照できるように。
この変換式を使って、角度を定義する。



したがって、30度の変化を行う場合は、

> (2*pi*30)/360
[1] 0.5235988

とりあえず、コピーアンドペーストで、変換行列を作成する。
まず、「d」という変数に、「30度」を弧度に変換して格納し、
さらに、行列の元となるベクトルを作成する。

d <- (2*pi*30)/360
v <- c(cos(d),sin(d),0,-sin(d),cos(d),0,0,0,1)

そして、作成したベクトルから変換行列を作る。

R <- matrix(v, nrow=3, ncol=3)

結果として、次のような行列ができる。

> R
          [,1]       [,2] [,3]
[1,] 0.8660254 -0.5000000    0
[2,] 0.5000000  0.8660254    0
[3,] 0.0000000  0.0000000    1

これから行う変換は、次の通りである。小数点四位以下は省いてある。
小数点を長々と書く意味は無い。計算機の都合を信じてはいけない。
まぁ、良いのだが。とにかく、以下のようになる。



Rでやってみる。実行結果は以下の通り。

> t(R%*%t(X))
       [,1]     [,2] [,3]
P1  0.00000  0.00000    1
P2 14.64102 54.64102    1
P3 34.64102 20.00000    1
P4  0.00000  0.00000    1

ふむ。なるほど!数値だけ見ても良く解らない。正しいのか?
ということで、可視化してみる。

plot(t(R%*%t(X)), type="b",col = "red", xlim = c(0,60), ylim = c(0, 60))
par(new=TRUE)
plot(X, type="b", col = "blue", xlim = c(0,60), ylim = c(0, 60))

実は、これらの変換は、一般的には「アフィン変換」と呼ばれるもの。
上記の変換以外にも、「せん断」という変換もできるが、今回は省く。
ちなみに、この変換では「台形」になる変換できないので注意が必要。

この変換は、画像処理やGISにおける空間データの変換など、
様々なシーンで利用されているので、覚えておくと応用が効く。
もちろん、行列を使わずに計算することもできるが、計算ミスの危険性は増大する。
行列で計算できるのであれば、行列で計算した方が楽なのである。

0 件のコメント:

コメントを投稿