画像の輪郭抽出の際に少し便利なアルゴリズム,XDoGがあると聞いたので,その論文の内容をまとめました.
XDoG
XDoG: An eXtended difference-of-Gaussians compendium including advanced image stylization
Holger Winnemoller, et al.(2012)
概要
ガウシアン差分(DoG)による輪郭抽出技術はその演算の拡張により,ノイズの影響を受けづらくより綺麗に抽出できるようになっている.本論文では,その可用性を強調したの画像処理との有用な関係性を説明する.また,DoGを応用することにより鉛筆画やパステル調への調整など,さまざまな芸術的な効果を簡単に得ることができることを示す.
導入
輪郭抽出は,その特性から様々な応用が見込める処理である.しかし,その視覚的特性はコンピュータビジョン的には最適であるようなものが多いものの,芸術的特性はあまり高くなく,複雑な後処理が必要である.
また,漫画やイラストから,DoGを応用することで,視覚的に良好な線画を抽出できることが既存研究から示されているほか,ある程度の芸術的結果が得られることは既存研究から示されているが,本項ではその潜在可用性に着目しさらなる応用を調査する.
この論文の貢献は以下である.
- DoGの理論と構成をつぶさに説明する.特にパラメータ値を従来の研究の範囲を超えて適用した場合の振る舞いについての説明に重点を置く.
- DoGを応用することで,さまざまな芸術的効果が得られることを示す.
- End-to-Endでスタイル変換を行う.既存の芸術的な輪郭抽出では様々なエフェクトにより達成されていたような複雑な処理を単純な,DoGのパラメータ空間を調整することにより達成可能で,既存のエフェクトに匹敵,もしくは超えるような制度を出すことができることを示す.
背景
勾配ベース輪郭検出
既存のSobelやPrewittといったフィルタリングは,小さなカーネルを近傍画素に適用することによって輪郭を検出させていた.こういったアルゴリズムは高速に動作するものの,ノイズに対しても敏感であることが問題であるため,高周波成分を除去するために,事前に画像にぼかしをかけるといったことが行われてきた.勾配ベースの中で最も用いられているCanny検出器は,複合的に画像を処理し,コンピュータビジョンの各分野で広く用いられている.しかしながらその結果は芸術的であるとはあまりいえない.
ラプラシアンベース輪郭検出
Canny検出器より以前に,二次導関数から,そのゼロ交差を検出するカーネルが提案されている.MarrとHilderethによるラプラシアンフィルタはその代表的な例である.
$$
\nabla^2=\frac{\partial^2}{\partial x^2}+\frac{\partial^2}{\partial y^2}
$$
ラプラシアンフィルタは二次導関数を元に輪郭検出を行うため,ノイズに対して浮上に敏感であるという問題がある.そのためノイズはブラーをかけて解消する.任意の高周波成分にぼかしをかけたいといった際にはガウシアンフィルタが非常に有効である.$x$を二次元座標とすると,ガウシアンフィルタは
$$
G_{\sigma}(x)=\frac{1}{2\pi\sigma^2}\exp\left(-\frac{|x|^2}{2\sigma^2}\right)
$$
と表記される.畳み込み演算を$\ast$のように表せば,ブラー→ラプラシアンという操作は以下のように変形ができる.
$$
\nabla^2(G_\sigma\ast I)=(\nabla^2G_\sigma)\ast I
$$
したがって,平滑化+微分という二つの動作が,一つの演算にまとめることができる.このようなフィルタはガウシアンラプラシアンフィルタ(LoG)としても知られている.
しかしながらこの演算を施したところで,芸術的な輪郭検出が行えるわけでもない.だが,このアルゴリズムはのちのDoGアルゴリズムの導入おいて重要な要素となる.DoGの前座として,LoGの高速推定法について考える.
ガウシアン差分フィルタ
LoGの限界というのは,それらが分離不可能であるという点である.そこでラプラシアンフィルタの発案者のMarr,Hildrethは分離可能な二つのガウス分布の差を用いてLoGを近似する手法を考案した.これがガウシアン差分(DoG)である.この方法の正当性は,ガウス分布の標準偏差の差を0へ極限をとることで証明ができる.すなわち,二つのガウス分布の微小変化量は
$$
\frac{G_{k\sigma}(x)-G_\sigma(x)}{k\sigma-\sigma}
$$
なので,これを$k\rightarrow 1$へと近づけていくと以下のようになる.
$$
\lim_{k\rightarrow1}\frac{G_{k\sigma}(x)-G_\sigma(x)}{k\sigma-\sigma}=\frac{\partial G_\sigma}{\partial\sigma}=\sigma\nabla^2G
$$
よって正当性を確認でき,その差分$D_{\sigma,k}(x)$は以下のように近似が可能である.
$$
D_{\sigma,k}(x)=G_{k\sigma}(x)-G_\sigma(x)\approx-(k-1)\sigma^2\nabla^2G
$$
DoGの有用な特性として,閾値$k$がスケールファクタ$\sigma$と無関係であるという点が挙げられる.すなわち,適切な感度というものを発見すれば,修正すべきパラメータはスケールファクタのみとなる.この閾値として,ここではMarrの論文と同様,$k=1.6$を用いる.
簡単に言えばガウシアンフィルタという二つのカットオフ周波数の異なるローパスフィルタの差分をとって輪郭の周波数に一致するようなバンドパスフィルタを近似的に設計していると言える.また,人間の受容野は,中心細胞の興奮と隣接細胞の励起同時興奮の拮抗系としてモデル化されているが,DoGはこの特性をよく表現している.
拡張ガウシアン差分フィルタ
ガウシアン差分フィルタも芸術的な輪郭からはまだ程遠い.そこで,ここではDoGを元にさらなる拡張を提案する.
ツートンの輪郭画像を生成するといった場合を考える.その場合以下の二つのような過程が考えられる.
- 真っ白な画像からはじめて,特定の領域を黒くしていく
- 真っ黒な画像からはじめて,特定の領域を白くしていく
DoGフィルタはバンドパスフィルタであるため,符号の変化というのは,近傍のピクセルからその画素を暗くすべきか,もしくは明るくすべきかという情報が与えられていると言える.そのようにして変換した画像を閾値DoG画像として形式的に$T_\varepsilon(D_{\sigma,k}\ast I)$とおく.ただし$T_{\varepsilon}(u)$は以下のように定義されるステップ関数である.
$$
T_{\varepsilon}(u)=\left\{\begin{array}{ll}1&u\geq \varepsilon\\ 0&\textrm{otherwise}\end{array}\right.
$$
コンピュータビジョン的にいえば画像の輪郭というのは,局所最大の勾配変化点により構成される細い線をさす際に使用する場合が多いが,画像の「スタイル」的文脈における輪郭というのは,上に示す例のような閾値により二値化したような画像を輪郭と呼ぶ方がふさわしい.
この単純な閾値DoGを拡張したものの例として,Winnemollerらによって定義したガウシアンの抑制効果の変容がより許容されるようなモデルとして以下のものがある.
$$
\begin{align}
D_{\sigma,k,\tau}(x)&=G_{\sigma}(x)-\tau G_{k\sigma}(x)\\
T_{\varepsilon,\varphi}(u)&=\left\{\begin{array}{ll}1&u\geq\varepsilon\\1+\tanh(\varphi(u-\varepsilon))&\textrm{otherwise}\end{array}\right.
\end{align}
$$
これらをまとめた$T_{\varepsilon,\varphi}(D_{\sigma,k,\tau}(x))$こそがXDoGフィルタリングである.
XDoGの再パラメータ化
XDoGのスタイルを容易に変更するために,以下の点を重視する.
- パラメータ間の相互依存性の除去
- 「ぼかし」「シャープ化」などの既存手法へのマッピング
- 可逆性
幸いなことにこれらの特性を得るためには以下のように$\tau-1$で割ることにより得られる.
$$
S_{\sigma,k,p}(x)=\frac{D_{\sigma,k,p(x)}}{\tau-1}=(1+p)G_{\sigma}(x)-pG_{k\sigma}(x)
$$
これにより画像のシャープ化演算子として定義できる.
あきらかに可逆であり,単純な式変形であるが,$p$をシャープ化のみをコントロールする演算子となる.
応用例
ハッチング処理
異なるパラメータで生成された画像をブレンドしてハッチング画像を作れる!
Pythonで実装する
OpenCVを使えば一瞬でおわるぞ!
# ガウシアン差分フィルタリング
def DoG(img,size, sigma, k=1.6, gamma=1):
g1 = cv2.GaussianBlur(img, (size, size), sigma)
g2 = cv2.GaussianBlur(img, (size, size), sigma*k)
return g1 - gamma*g2
# 閾値で白黒化するDoG
def thres_dog(img, size, sigma, eps, k=1.6, gamma=0.98):
d = DoG(img,size, sigma, k, gamma)
d /= d.max()
d *= 255
d = np.where(d >= eps, 255, 0)
return d
# 拡張ガウシアン差分フィルタリング
def xdog(img, size, sigma, eps, phi, k=1.6, gamma=0.98):
eps /= 255
d = DoG(img,size, sigma, k, gamma)
d /= d.max()
e = 1 + np.tanh(phi*(d-eps))
e[e>=1] = 1
return e
# シャープネス値pを使う方
def pxdog(img, size, p, sigma, eps, phi, k=1.6):
eps /= 255
g1 = cv2.GaussianBlur(img, (size, size), sigma)
g2 = cv2.GaussianBlur(img, (size, size), sigma*k)
d = (1 + p) * g1 - p * g2
d /= d.max()
e = 1 + np.tanh(phi*(d-eps))
e[e>=1] = 1
return e
課題
- このXDoGをGUI化する
- 上記論文中ではフローベースのFDoGが提案されていた.これも実装したい.