Bilateral Solverをソルブする(第2回)
艦これ改が発売となりましたね!提督の一人としては是非とも購入したいところですが、PS vitaがない。これだけのために買うべきだろうか・・・?しかし高いしなぁ。
さて、Bilateral Gridの話でしたね。最近はいろいろあった(特に何もない)ので進捗が遅いですね・・・。しかし!ほぼ完璧に理解することができました!今回はその完結編です。
Birateral Gridのアルゴリズム
Bilateral Gridは①splat ②blur ③slice の3つの処理で構成されます。1次元信号を用いて説明します。
①splat
今回のサンプル信号は(0〜255)の値をとるサンプルが500個で構成されます。Bilateral Gridの格子パラメータをσ_scale = 5、σ_range = 3とすると、作成される格子は(500/5, 255/3) = (100, 85)の二次元配列になります。
サンプル信号をBilateral Grid上にプロットします。説明のため各サンプルを(number, value)、Bilateral Grid上の座標をB(x, y)と表記します。例えば、(0, 9)のサンプルはB(0/5, 9/3) = B(0, 3)にプロットされます。(6, 4)のサンプルは、少数点以下四捨五入でB(6/5, 4/3) = B(1, 1)です。この時、プロット先のグリッドに値とカウントを保存しておいてください。
なぜカウントを保存するかというと、Bilatera Grid上の一つの座標に対して、複数のサンプルが対応する可能性があるからです。この時は保存する値を、その総和としてください。サンプル信号を全てプロットしたものを下図に示します。
図中の紫の領域は、単純に対応するサンプルがなかったことを示します。あくまで視覚に配慮したものなので、特に意味はありません。また図中の下は黒色、上は白色に着色していますが、これは保存されている値の大きさを示したものです。
②blur
Bilateral Grid上の値を適当にぼかしてください。ガウシアンフィルタでもいいし、移動平均でもいいと思います。
私が少し困ったのが、値の無い場所(紫)をどうやってボカすのかです。工夫のしどころだと思うのですが、
(フィルタカーネル内の値の総和)/(フィルタカーネル内のカウントの総和)
で計算することにしました。当然カウントの総和が0であれば、0除算になるので例外処理とします。
③slice
サンプル信号と、Bilateral Gridから出力信号を得ます。
各サンプルの(number, value)から、Bilateral Grid上の値value_Bを参照し、出力を(number, value_B)とします。参照の方法は①splat処理と似ているのですが、一つ注意が必要です。slice処理では少数点をカットせずに使用します。例えばサンプル(6, 4)であれば、B(6/5, 4/3) = B(1.2, 1.33)です。小数点以下の計算には、B(1, 1), B(1, 2), B(2, 1), B(2, 2)の全てを参照して、線形補間します。
元のサンプル信号(ピンク色)と、slice処理後の出力信号(緑色)を下に示します。大きなエッジはそのままに、小さなエッジが抑制されていることを確認できます。
以上がアルゴリズムの概要です!詳しい数式は元論文を参照願いします。
画像への応用
アルゴリズムを画像に適用します。画像はXとYに空間成分をもち、かつRGBのチャンネルがあることを考慮します。Bilateral Gridは3次元配列のものをR,G,Bの3つ用意しました。例にならって、レナの画像でテストします!
入力画像
出力画像
こころなしかザラザラ感がとれた気がします。
3次元ブラシ
元論文によるとBilateral Gridは3次元ブラシをイメージして考案されたもののようです。3次元ブラシとは、エッジを検知して色を塗る/塗らないの判定を行う機能をもつブラシらしいです。レナの画像でいうと、レナを色塗りしている間にブラシが背景領域にはみ出しても、それを無効にするというイメージでしょうか。
アルゴリズムとしては、Bilateral Grid上の値を強制的に書き換えます。こうすると、Slice処理で参照するBilateral Grid上の座標をそのままに、取得する値が変化します。
簡易的にプログラムを組んでみました。画像は「のんのんびより」から引張てきてま
す。
入力画像がこちら。
れんちょんのズボンの色を変更してみます。 Bilateral Gridを用いたブラシで、ズボンの上をテキトーになぞります。テスト中のスクショが下。地味にこのGUIを作るのに苦労しています・・・・。色は蛍さんのランドセルからコピーしてきました。
そして出力画像がこちら!
やっぱれんちょんはかわいいなぁ・・・・・。
∑( ̄Д ̄;)はっ!
出力画像についてですが、いい加減になぞったにしては上出来ではないでしょうか・・!(境界線が微妙?まぁ、こういうのは色を専門に扱う人達が頑張ってください)
ソースコードは今は汚いので、そのうち公開できたらというところです。以上!