もうすでに何度もこのブログでは当たり前の様にフィルタ処理〜とかたたみ込み〜とか言っていますが、今後の記事の内容のために、ささっとまとめておきます。
フィルタをかける
フィルタをかける操作って言うのは、「フィルタの値×ピクセルの値」を各フィルタの値に対して計算して、それらを足し合わせます。これを全ての画素についてやっていくのです。言葉だとなんだかよくわかりませんから、画像で説明します。
下の画像で、青いピクセルに、3×3の大きさのフィルタをかける時を考えます。この時フィルタをかけた後の青いピクセルの値は「a×紫+b×緑+c×赤+....」と計算されます。
端はどうするの?
上の図で言うと、青いピクセル以外のピクセルだと、フィルタをかけるためのピクセルが足りません。この時は「処理しない (元の画素の値をそのまま結果とする)」か「画素の値を補間する」か、「フィルタのサイズを適宜変更する」の中のどれかを利用します。
画素の値を補間するには
- 黒(0)や白(1)で補間する
- 最も近い画素の色で補間する
- 画像をループまたはミラーしているものと扱う
などがあります。
フィルタのサイズを変更するときは、たとえばフィルタの値の総和が1である、などの縛りがある場合、それに合うように値を書き換える必要があります。
たたみ込みって何じゃ〜
たたみ込みって単語を聞くだけで頭痛が………という人もいるかもしれませんが、大して難しくありません。畳み込みって言うのは関数fと関数gを合成して新しい関数f*gを作る操作です。
連続系では
離散系では
っていう形になります。二次元では
となります。(範囲の-∞〜∞は省略しました)
まぁ、難しいことは考えず、こういう定義なんだ〜と盲目的に受け入れてしまえばいいでしょうヽ( ・∀・)ノ
フィルタをかける作業も畳み込み
再度下の図を見てください。
「a×紫+b×緑+c×赤+....」という式をもうちょっと見通しをよくしましょう。
青いピクセルを原点とした画像の位置(x,y)の画素の値をf(x,y)、eを原点としたフィルタの位置(x,y)の値をg(x,y)としましょう。すると、
「f(-1,-1)g(-1,-1)+f(0,-1)g(0,-1)+f(1,-1)g(1,-1)+f(-1,0)g(-1,0)+f(0,0)g(0,0)+f(1,0)g(1,0)+f(-1,1)g(-1,1)+f(0,1)g(0,1)+f(1,1)g(1,1)」
となります。簡潔に書くと
ですね。ここで、少しだけ関数gの見方を変えてみます。
g'(x,y)=g(-x,-y)
と座標変換してみましょう。そうすると、上の式は
と書き換えることができます。ここで、g'(0-x,0-y)にわざわざ出てくる0は青いピクセルの座標を表します。
そう、つまり、これは関数fと関数g'の畳み込みってことなんですね。
今回以降の記事では
の形状の式も、フィルタをかけるという作業に関しては(座標変換すれば)畳み込みであると扱います。(だから噛みつかないでね(`・д´・ ;) )
ふぅ、これで今回の記事で一番大切なことはいえた(´・д・`)
画像処理で重要な畳み込みの性質
フーリエ変換すると単にかけ算になる
非常に有名な性質ですね。畳み込みをフーリエ変換すると、合成する関数をフーリエ変換した物の積になります。
畳み込みと微分の演算は可換
証明は省きますが、
というのも、重要な性質です。
しまった、理論の話ばっかりでJava関係ねぇ!(`・д´・ ;)
でも行数も長くなってきたので、今回はここまで…。