プログラムdeタマゴ

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

画像を拡大してみよう。


縮小の時同様、元の画像(領域M)を拡大(領域M')する関数をFとする。
この時Fは紙の上では元の画像の範囲にある点を拡大先に全単射する関数となる。
が、残念ながら縮小時同様にPC上の画像は紙や数学上とは違い有限の点からなる。つまり、M上の全ての点の集合U、M'上の点の集合をU'とし、ある自然数nに対して |U| < |U'| < nが成立する。
よってMからM'への遷移関数Fは全射とはならない事が証明された。 全射にならないと言うことは、拡大先に代入されない画素が存在すると言うことである。(ちなみに、縮小の時は単射にならなかったことが問題であった。画像をもとの情報を失わずに変形処理する際、重要なのは元の画像に作用させる関数が全単射であることである。)
そこで、この問題を解決するために領域M'から処理を行うのだ。 


さて、拡大画像上のPから元画像のP'を求めるのは単純に
P' = P*(1/x軸方向の拡大率,1/y軸方向の拡大率)
で求まる。ちなみに、以下英字の太文字はベクトル扱いです。

さて、このP'が整数となってくれればいいのだが、そうも行かない。さて、どうしたものか。

一つの簡単な方法に[P']としてしまう方法がある。
最近傍法と呼ばれる補完方法だ。
この方法は元の状態をそのまま保持する。簡単に言えば、画像をn倍すると1ピクセルの大きさがnピクセル相当になるような物。ピクセル情報をそのまま表示したいとか言う場合でない限り残念ながら使えるような拡大方法ではない。


そこで、周囲の色からP'=(x,y)の色を判断するという内挿を行う必要が出てくる。

そのなかで、一番単純なのが線形補完。
X=(1,0) Y=(0,1)の単位ベクトルとし、
a,b,c,dをそれぞれ[P'],[P']+X,[P']+Y,[P']+X+Yの色とするとP'の色は
F(P') = (1-y+[y])*((1-x+[x])*a + (x-[x])*b) + (y-[y])*((1-x+[x])*c+(x-[x])*d)
という式で与えられる。

まぁ〜、ぶっちゃけこれで構わない気がするんだけど、この方法で拡大を行うと輪郭がぼやける。
これは線形補完の当然の性質で、元の画像の色の変化の度合い(要するに微分した値)を保持しないからである。

そこで、曲線関数で内挿を行う。

関数は三次関数で補完するラグランジュ補完というものがあるが、今回はこれではなく、sinc関数を利用した三次畳み込み内挿法(キュービックコンボリューション)という方法で内挿する。


色を求めたい点Pに対して以下のような座標で色G00 〜G33を求める。




上図そのままの形でGxyを行列化した4×4の正方行列を行列Gとする。

また、GxyにおいてXxを点Pとのx軸上での距離、Yyを点Pとのy軸上での距離とし、関数F(t) = sin(π|t|) /π|t|とする。
ちなみに、F(t)は-∞〜∞までを積分すると1になるので確率密度関数として使えるわけですね。

このXx,Yy,Fについて、順にF(Y0),F(Y1),F(Y2),F(Y3)を要素とする「4×1」の行列Aと、順にF(X0),F(X1),F(X2),F(X3)を要素とする「1×4」の行列Bを定義する。

この時Pにおける求める色は
A×G×Bで与えられる

と、行列を書くのがしんどいから文字で頑張ってみたが、非常にわかりにくいね。

ググったらこんなPDFが合ったのでこっちを参照して貰っても良い。ここで言うFがHに、GがFになっています。
PDF

実際にF(t)をそのまま計算するのではなくて、近似式で計算します。
0≦ |t| <1の時
F(t) = (a +2) |t|^3 - (a+3)|t|^2 +1
1≦ |t| < 2の時
F(t) = a|t|^3 -5a|t|^2 + 8a|t| -4a
2 ≦ |t| の時
F(t) = 0
という風に。a は元のF(t)に合わせて-1で計算しました。


もし読んでる人がいたら正直もう疲れたと思うが、私も疲れるんだぜ。( ´∀`)

さて、以上でとりあえず、色を求めることが出来ましたので、これで解説は終わります。

前回縮小した物を5倍に拡大してみた物↓


エッジがあまりぼやけることなく拡大できています。
ただ、元の画像がJPEG圧縮でがたがたになっているのでサンプルが悪かったかなぁ〜





追記的な内容:キュービックコンボリューション(3次畳み込み内挿法)