2016. 8.13.
2017. 9.28. OpenCV3.3.0とVisual C++ 2017で確認済み、このままのプログラムで使用可
石立 喬

OpenCV3.1.0とVisual C++ 2015による画像処理と認識(6)

----- エッジ保存平滑化フィルタを比較する -----

 これは「OpenCVとVisual C++による画像処理と認識(6)」の続編と言えるもので、ノイズ除去を目的とした各種平滑化フィルタのうち、特にエッジ保存機能を持った平滑化フィルタについて、その効果と処理実行時間を比較した。平滑化フィルタの一般的な説明については、前記資料を参照されたい。

平滑化フィルタとエッジ保存平滑化フィルタ
 平滑化を目的としたフィルタ関数は、画像からノイズを除去するのが主目的である。mgprocモジュールのImage Filteringサブモジュールについて見ると、一番簡単なblur関数は、周辺ピクセルの単純平均をとるもので、ノイズ除去の効果が大きい。GaussianBlur関数は、中心の比重が高く、ノイズ除去の効果は控えめであるが、きれいなボケ味がある。medianBlur関数は、単独ピクセルのインパルス的変化を除去するのに、非常に効果的である。エッジ部分をぼかさないでノイズを除去する、エッジ保存平滑化フィルタには、bilateralFilter関数がある。
 なお、OpenCV2.4にはあったadaptiveBilateralFilterがOpenCV3.0からなくなっている。
 imgprocモジュールのImage Filteringサブモジュール以外で、photoモジュール(Computational Photography)のDenoisingサブモジュールに属するfastNlMeansDenoisingColored関数も、エッジ保存が可能な類似した関数で、OpenCV3.0から追加された、photoモジュール→Non-Photorealistic RenderingサブモジュールのedgePreservingFilter関数も、文字通りエッジ保存平滑化フィルタである。

いろいろな平滑化フィルタを比較するプログラム
 図1と図2は、使用したプログラムで、図1はプロジェクトの最初の部分と、原画像にノイズを付加するユーザ関数を示す。乱数発生と実行時間の測定と表示のために、関連のインクルードファイルや名前空間を指定してある。図2は、各種フィルタを順次実行させるプログラムで、特に説明の必要はないと思われる。
 図1に示すaddNoise関数は、下記から成る。
 1)原画像srcをコピーして、画像image_noiseを用意する。
 2)0中心の正規分布の乱数を発生するクラスのnoiseを用意する。
 3)座標位置x、yを乱数で求め、それまでのimage_noizeのBGR各ピクセル値にnoise(gen)を加算する。
   加算により、ucharの範囲を超える場合があるので、staurate_cast<uchar>を使用する。

使用したOpenCV関数の説明
 エッジ保存平滑化フィルタ関数について、以下に説明する。その他の平滑化フィルタ関数については、「OpenCVとVisual C++による画像処理と認識(6)」を参照されたい。
◎bilateralFilter関数
 imgprocモジュール→Image Filteringサブモジュールに含まれている。
 座標空間(space)における距離と色空間(color)における濃淡の双方を使用し、色空間での変動が激しい場所(エッジ)では、座標空間に対する重みを低減させて、平滑化の影響を少なくする。二つの条件を加味するため、bilateralと呼ばれる。
   bilateralFilter(
     src --------- InputArray、カラーまたはグレイスケール入力画像
     dst --------- OutputArray、入力画像と同じサイズ、タイプの出力画像
     d ---------- int、フィルタに使用する近傍円の直径、負数の場合は、sigmaSpaceから自動的に求める
     sigmaColor -- double、色空間の標準偏差
     sigmaSpace -- double、座標空間の標準偏差
     borderType = BORDER_DEFAULT ------- int、周辺を鏡像のように折り返す、最も一般的
   )
◎fastNlMeansDenoisingColored関数
 imgprocモジュール→Image Filteringサブモジュールに含まれていないので、気が付きにくいが、photoモジュール→Denoisingサブモジュールに属する、ノイズ除去を目的とした関数の一つである。
 non-local meansは非局所平均法と言われる。画像内の全域から、対象の場所と類似の場所を探して、類似度が大きいほど重みを増やして平均を取るからで、画像全体(non-local)が対象となる。
   fastNlMeansDenoisingColored(
     src ---------- InputArray、カラー入力画像
     dst ---------- OutputArray、入力画像と同じサイズ、同じタイプ
     h = 3 -------- float、輝度成分のフィルタの平滑化の度合い、大きいとノイズが減少するが、エッジ部にも影響する
     hColor = 3 ---- float、色成分のフィルタの平滑化の度合い、10にしておけば十分
     templateWindowSize = 7 ---- int、重みを計算するのに使うテンプレート・パッチの辺の長さ(奇数に限る)、7を推奨
     searchWindowSize = 21 ---- int、加重平均を取るウィンドウの辺の長さ(奇数に限る)、21を推奨
   )
◎edgePreservingFilter関数
 OpenCV3.0から追加された、photoモジュール→Non-Photorealistic Renderingサブモジュールに属す。domain transform(定義域変換法)と言う原理に基づく。RGB色情報と、x、y座標位置情報を合わせると多次元のフィルタが必要になるが、変換式により一次元化し、漸化式による繰り返しで処理する。
   edgePreservingFilter(
     src -------- InputArray、カラー入力画像
     dst -------- OutputArray、カラー出力画像
     flags = 1 ---- int、下記参照
     sigma_s = 60 ------- float 0〜200、座標空間の標準偏差
     sigma_r = 0.4f ------ float 0〜1、色範囲の標準偏差
  )
 flagsには、
     RECURS_FILTER ( =1) ------ 精度はやや低いが、高速、推奨
     NORMCONV_FILTER ( =2)
がある。


図1 各種宣言部と、原画像にノイズを付加するユーザ関数




図2 各種フィルタを比較するプログラム


得られた結果
 図3は使用した原画像と、ノイズを付加した画像で、空と道路など、比較的テクスチャのない部分で、ノイズを確認できる。
 図4は、ノイズ付加原画像に、各種の単純な平滑フィルタを実施した結果を示す。これらの結果では、ノイズも減少しているが、同時に、全体的にシャープさが失われている。
 図5は、エッジ保存平滑化フィルタを使用した場合で、左上は、比較のために再度表示したノイズのない原画像、右上は従来からあるbilateralFilter、左下も従来からphotoモジュールにあったfastNlMeansDenoiseCorered、右下はOpenCV3.0から導入されたphotoモジュールのedgePreservingFilterの結果で、いずれも甲乙つけがたく、特定条件での主観的な判断であるが、強いて言えば、右下のedegPreservingFilterがシャープさで優れているのかな、と思われる。


図3 原画像(左)と、各種平滑化フィルタの比較に用いたノイズ付加原画像(右)



図4 ノイズ付加原画像(比較のため再表示)と各種フィルタ使用結果



図5 ノイズのない原画像(比較のために再表示)と各種エッジ保存フィルタ使用結果


実行時間の確認
 bilateralFilterは、実行速度が遅いと言われてきた。新規に追加されたedgePreservingFilterはどうかと思い、これらのフィルタを含め、すべてのフィルタについて、実行時間を測定した。
 プログラムの要部は、図6に示してある。図2に示したように、chronoのインクルード、std::chronoの名前空間指定が必要である。時間の測定方法については、「OpenMPとVisual C++による並列処理(1)」を参照されたい。
 図7はRelease構成での実行時間測定結果で、、bilateralFilterに比べて、edgePreservingFilterの高速化ぶりには感心する。fastNlMeansDenoisingColoredは、動作原理が異なることもあり、桁違いに遅いことが分かった。Debug構成とRelease構成で比較したところ、有意な差は見られず、むしろ実行の都度のバラツキの方が大きかった。


図6 各種フィルタの実行時間を測定するプログラム(抜粋)



図7 各種フィルタの実行時間、edgePreservingFilterの優秀性が確認できた


結 論
 全画面を無差別に一様に平滑化するのではなく、エッジは保存しながら、ノイズと思われる部分のみを重点的に平滑化するエッジ保存平滑化フィルタの効果と処理時間を調べた。従来からある、imgprocモジュールのbilateralFilterは、十分な性能を示すが、OpenCV3.0から用意されたphotoモジュールのedgePreservingFilterは、それに勝るとも劣らず、実行時間が半分以下と言う、素晴らしい成績であった。
 従来からphotoモジュールにあったFastNlMeansDenoisingColored関数も試みたが、性能は、他のエッジ保存ノイズ除去フィルタと同程度で、実行時間が非常に長いのが気になった。
 これらの結論は、すべて、ここで使用した画像とパラメータ設定、CPUによって得られた主観的な結果である。

参考文献
 bilateralFilter関数
 C. Tomasi他、"Bilateral Filtering for Gray and Color Images" (1998)
 https://users.cs.duke.edu/~tomasi/papers/tomasi/tomasiIccv98.pdf

 fastNlMeansDenoisingColored関数
 A. Baudes他、"A Non Local Algorithm for Image Denoising" (2005)
 http://audio.rightmark.org/lukin/msu/NonLocal.pdf

 edgePreservingFilter関数
 E.S.L. Gastal他、"Domain Transform for Edge-AwareImage and Video Processing" (2011)
 http://inf.ufrgs.br/~eslgastal/DomainTransform/Gastal_Oliveira_SIGGRAPH2011_Domain_Transform.pdf






「Visual C++の勉強部屋」(目次)へ