読者です 読者をやめる 読者になる 読者になる

プログラムdeタマゴ

nodamushiの著作物は、文章、画像、プログラムにかかわらず全てUnlicenseです

画像処理を始めよう -行列の基礎-

 さて、どれほど根性続くかわからないけど、いままでブログに書いてきた簡単な画像処理の話じゃなくて、もっと専門的な画像処理の話を書いていこうと思う。というのも、私来年から画像処理屋じゃなくなる予定なので、今のうちにまとめとかないとわからなくなる可能性大なのよね。



画像と行列

 何から書き始めようかと思ったけど、とりあえず行列の話から。画像処理において、行列は非常に大事です。画像はコンピュータ上では行列として扱っていますからね。


 連続空間において色や輝度値の関数がf(x,y)と与えられたとき、計算機上で扱う画像はI(x,y)=f(ax,ay) (x,yは自然数、aは正の定数)となります。aはサンプリングレートの逆数です。サンプリングレートあたりの話は過去に何度か書いたので省略します。このIが行列として表されるわけですね。



行列の固有値と固有ベクトル

 線形代数で習うあれ。私は当時はなんか問題解けと言われてたから解いてたけど、正直必要性や意味はわかってなかったw

 画像やると死ぬほど出てくるので、一応解説することにしました。


 長さnのm=(x,y,z,...)ベクトルにn×nの正方行列を作用させることを考えてみましょう。

Am = m'

 すると、m'=(x',y',z',....)というベクトルが出てきました。Aはmをm'に変換する作用素と見なすことが出来ますね。見やすくするためにここではn=2としましょう。
A=\left(\begin{array}{cc}a&b\\c&d\end{array}\right)
とすると、x' = ax+by,y' =cx+dyですね。


 ………う〜ん、そう言われても、意味わからん。何言いたいんすかね?この変換。もっと分かりやすく、x'=ax,y'=byとかだったら単純でエエのに(´・д・`)


 その、もっと分かりやすいx'=ax,y'=byという変換にするために必要なのが固有値と固有ベクトルになります。



 今、作用素Aでは方向が変化しないベクトルがあると仮定しましょう。いま、Aは2×2の行列なので二つぐらいそんなベクトルk,lがあったらえぇなぁ。なぜかというと、

Ak = \lambda_k k
Al = \lambda_l l
ですから、一般に二次ベクトルxはk,lを用いて
Ax = A(\alpha k+\beta l)=\alpha Ak+\beta Al = \alpha\lambda_k k + \beta\lambda_l l
と表現できるわけです。いいですねー。


 え?何が言いたいのって?

 ベクトルkとlを基底ベクトルとする新たな座標系(k,l)を考えると、元のベクトルxは(α,β)という座標になります。xにAを作用させたときの変換というのは、この新たな座標から見た時に、\alpha'=\lambda_k \alpha,\beta' = \lambda_l \betaという単純な変換に見えるんです。


 このk,lを固有ベクトル、λ達を固有値というのですが、要するに変換が簡単に見える座標系を探そうという話なんですね。


 でももちろん、あれば良いなぁ程度の話でしたので無いこともあります。一個しか無いこともあります。でもそれらのことも併せて変換Aの特徴だと見なすことが出来ますね。


固有値の性質

 画像処理をやる上で知っておくべき固有値の性質は大体下の二つ知っていればおk。おまけで説明する対角化を使えば簡単に証明できるので、証明は省略。
\det(A) = \prod_i \lambda_i
\text{trace}(A) = \sum_i\lambda_i



固有ベクトルの性質

 新たなkl座標系が作れると言うことは固有ベクトルk,lが一次独立でなくてはならない。先の説明では何の説明もなく固有ベクトルk、lが一次独立であることを前提にした。別に誤魔化したわけではなく実際にk,lは一次独立である。証明等はここでは省く。数学的帰納法による証明



 あとは、Aがエルミート行列(A=A^*となる行列)だと固有ベクトルは直交するってことも重要かな。この辺は分散共分散行列を扱うと出てくるよ。こっちの証明は簡単で
\lambda_lk^tl = k^tAl = (Ak)^tl = \lambda_kk^tl
より、
(\lambda_l-\lambda_k)k^tl = 0
である。異なる固有値の差が0にはならないから、k,lの内積が0である。したがって、k,lは直交する。




おまけ:行列の対角化

 所詮ごりごり計算するか、固有値解析ぐらいしかしないので行列の対角化の話が必要になったことって今のところ私は無いけど、一応。


 元の座標での変換行列Aも座標系(k,l)での変換行列A'も同じテンソルだよね。なお、
A'=\left(\begin{array}{cc}\lambda_k&0\\0&\lambda_l\end{array}\right)
です。この形を対角行列と言います。

 さて、同じテンソルなんだからA'への単純な変換があるはずだ。そこで、とりあえず、AからA'を作ってみよう。最も単純なのはAに固有ベクトルkとlを作用させて固有値を出すのがいいだろう。

A(k\,\,l)=(\lambda_k k\,\,\lambda_l l)=(k\,\,l)\left(\begin{array}{cc}\lambda_k&0\\0&\lambda_l\end{array}\right)=(k\,\,l)A'



 ん、簡単にAからA'が出てきた。ここで(k l)=Pと置くと
P^{-1}AP=A'
である。簡単だね。A'は対角行列なのでAを対角化できたと言うことだ。





 というわけで、行列の話はおしまいです。次回は分散あたりの話かな。しばらく基礎が続くね。