OpenCVのエッジ保持平滑化フィルタ

#はじめに

エッジ保持平滑化フィルタとは，大きなエッジを保持しつつ，小さなエッジだけをなめらかにスムージングするように意図されたフィルタです．

このエッジ保持平滑化フィルタは，ノイズ除去を筆頭に，コントラスト強調やヘイズリムーブ，ハイダイナミックレンジ画像，ステレオマッチングやオプティカルフロー，セグメンテーションなどのラベリング問題の最適化のミーンフィールドソルバとして使われています．

以下にエッジ保持平滑化フィルタを適用した例を示します．左から順に，入力画像，平滑化画像，入力画像から平滑化画像の差分を強調した詳細強調です．
![epf.jpg](https://qiita-image-store.s3.amazonaws.com/0/67908/85c9222a-33c2-738a-96ad-352c74d9ef4b.jpeg)

#OpenCVの実装
エッジ保持平滑化フィルタは現在，様々なモジュールに入っています．

* **imgproc**
 * bilateralFilter: バイラテラルフィルタ
 * pyrMeanShiftFiltering: ミーンシフトフィルタ
 * adaptiveBilateralFilter: アダプティブバイラテラルフィルタ(OpenCV3.0から~~行方不明~~削除されました．)
* **photo**
 * fastNlMeansDenoising: 高速化されたノンローカルミーン（あまり速くない）
 * fastNlMeansDenoisingColored: 上記のカラー版
 * denoise_TVL1: TVL1最小化を用いたデノイジング
 * edgePreservingFilter: ドメントランスフォームフィルタ(RECURS_FILTER** = 1, NORMCONV_FILTER** = 2)
* **contrib - ximgprocphoto**
 * jointBilateralFilter: ジョイントバイラテラルフィルタ
 * guidedFilter: ガイデットフィルタ
 * dtFilter: ドメイントランスフォームフィルタ
 * amFilter: アダプティブマニフォルドフィルタ
 * fastGlobalSmootherFilter: セパラブルなL1スムージングファイル
* **contrib - xphoto**
    * dctDenoise

#簡単な解説

[バイラテラルフィルタ](http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html)は，もっとも基本的なエッジ保持平滑化フィルタです．画素間のカラーとスペースの両者の距離に応じて近ければ近いほど重みが大きくなるフィルタです．

[ミーンシフトフィルタ](http://www.ekran.org/ben/wp/2011/mean-shift-segmentation/)はほぼ繰り返しバイラテラルフィルタといえます．大きなエッジしか残らず細かなエッジは全て消えるでしょう．

[アダプティブバイラテラルフィルタ](http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=4380043&tag=1)は画素毎にバイラテラルフィルタのパラメータを変更するフィルタです．この実装では，文字を圧縮したときに出るモスキートノイズなど，細かなノイズを抑えつつ輪郭が強調されるように設定されています．なお，OpenCV3.0では~~行方不明です．~~削除されました．使用したい場合は，古い2系を使って下さい．

ノンローカルミーンフィルタは，バイラテラルフィルタをパッチを使った形へ変形したものに近いです．バイラテラルフィルタに比べて，平滑化度合いは下がりますがノイズを検出し除去する能力が強まっています．
なお，OpenCVの実装が少々残念な，ブルートフォースな私の実装([OpenCV.jpのサンプル](http://opencv.jp/opencv2-x-samples/non-local-means-filter)]よりもほとんどの場合で遅いです．

TVL1によるデノイジングは，超解像等に良く用いられる近隣画素とのL1ノルムを最小化するフィルタです．ノイズ除去に特化されて作られています．なお，現在挙動が非常に怪しいです．

edgePreservingFilterと書いてあるこのフィルタの実体は[ドメイントランスフォームフィルタ](http://inf.ufrgs.br/~eslgastal/DomainTransform/)の実装です．ドメイントランスフォームフィルタは1次元信号に対して，バイラテラルフィルタのような平滑化を非常に効率的に実行する方法です．これを2次元にすこし強引に拡張することでエッジ保持平滑化フィルタとして用いています．なお，ドメイントランスフォームフィルタはOpenCVに多重に定義されており，後で紹介する実装のほうが優れています．

ジョイントバイラテラルフィルタは複数枚の入力画像を使ってバイラテラルフィルタを計算するフィルタです．例えば，フラッシュを焚いたノイズの少ない画像と，フラッシュを焚かない質感のある画像を合わせてフィルタすることで優れたデノイジング効果を発揮します．
詳しくは，[私のスライド](http://www.slideshare.net/FukushimaNorishige/ss-11861123)を参考にして下さい．

ガイデットフィルタは，局所線形性を用いたエッジ保持平滑化フィルタです．画像のボケや，グラデーションなどの勾配のある画素に対して効果的なフィルタです．また，平滑化するカーネルの大きさに非依存かつ非常に簡単に実装できるためmatlabを用いた実験で大人気です．なお，カーネルを大きく取ると仮定が破綻するため，使い方には注意が必要です．

dtFilterとかかれたドメントランスフォームフィルタです．この中のリカーシブル実装は非常に高速でガイデットフィルタと同様に平滑化の範囲に非依存（どれだけ広い範囲で平滑化しても計算時間は同じ）です．使うならこちらを使いましょう．

アダプティブマニフォルドフィルタは，ノンローカルミーンフィルタを高速化する用途に使えるフィルタです．ただしデノイジングパフォーマンスが劣化してます．

fastGlobalSmootherFilterは，[最適な局所線形をとくために必要なフィルタ](http://cs.brown.edu/courses/cs129/results/final/valayshah/) をセパラブルな状態で近似高速化するフィルタです．多少ノイズに頑健でガイデットフィルタのような効果をより高速に得たい場合に使えます．

dctDenoiseは，ノイズ除去のためのフィルタです．ただ平滑化するだけでなく，周波数領域の処理を含むため，他のエッジ保持平滑化フィルタでは失われる模様も，周期的な模様の場合は保持される傾向にあります．
なお，OpenCVが参照している[論文](http://www.ipol.im/pub/art/2011/ys-dct/)の数式は，ノイズが多い場合のカラーへのデノイジング性能が非常に悪いです．また実装も，将来GPUを使うために作られてるような形のため非常に遅いです．より高速・高精度なアルゴリズムと実装が必要な場合は，この[プロジェクト](http://fukushima.web.nitech.ac.jp/research/rrdct/)を使って下さい．限界までDCTを高速化しています．

#まとめ
OpenCVのエッジ保持平滑化フィルタを紹介しました．このエッジ保持平滑化フィルタは，コンピュータビジョンというよりも基本的な画像処理のツールです．しかし，このエッジ保持平滑化フィルタは，画像加工やコンピュテーショナルフォトグラフィにとって基盤的な技術になりつつあります．加えて，MRF最適化の手法の一部としても使われており，非常に応用範囲の広いトピックです．

現在使用可能なエッジ保持平滑化フィルタは，OpenCVの実装と私の実装の[OpenCP](https://github.com/norishigefukushima/OpenCP)位しかありません．必要な場合はこれらを参考にして下さい．また，@Schimaさんの[この解説記事](http://schima.hatenablog.com/entry/2014/02/18/202606)も参考になります．

#備考
denoise_TVL1とfastGlobalSmootherFilter以外，前回紹介したOpenCPにも実装があります．OpenCVの実装に比べて数倍からものによっては(dctDenoise)数百倍高速です．