Non-local Means Filterによるデノイジング
Non-local means filterと呼ばれるフィルタによるノイズ除去処理のデモンストレーションです.このデモは下記論文の実装です.詳細はそちらで確認して下さい.テクスチャ(模様)の多い画像などで,特に効果を発揮し,バイラテラルフィルタよりも効果の高いフィルタとなります.
A. Buades, B. Coll, J.M. Morel “A non local algorithm for image denoising”
IEEE Computer Vision and Pattern Recognition 2005, Vol 2, pp: 60-65, 2005.
下のデモンストレーションビデオでは,画像にガウシアンノイズを付加し,様々な手法とこのNon-local means filterでのノイズ除去をデモンストレーションしています.
質問等やバグ報告は@fukushima1981(Twitter)までどうぞ.
※ 下記質問に対するバグ修正(とコードの最適化)を行っております.(2011/11/23)
C++
(1)画像の読み込みとノイズの付加
画像を読み込み,標準偏差15のガウシアンノイズを付加します.
(2)比較手法の画像品質をPSNRで評価
下記手法で,ノイズ除去をしたのちに,原画像と比較することでPSNRを求めます.
(2−1)フィルタなし(処理無し)
(2−2)ガウシアンフィルタ(7x7),標準偏差5
(2−3)メディアンフィルタ(3x3)
(2−4)バイラテラルフィルタ(7x7),色標準偏差35,位置標準偏差5
(3)Non-local means filterの概説
Non-local means filterとは,適応的な重みを持つサポートウィンドウのコンボルージョンによりノイズリダクションするフィルタで,エッジキープ型のフィルタとなります.その重みは,カーネル中心まわりにサポートよりも小さなテンプレートを作成し,テンプレートマッチングによりサポートウィンドウ内の類似度(重み付きユークリッド距離,L2ノルムのエクスポネンシャル)を各位置ごとに求めていきます.その類似度により,テンプレートに似ている位置の重みを大きく,似ていない位置の重みは小さく設定されます.図に概略を示します.
また,類似したフィルタには,バイラテラルフィルタがあり,Non-local means filterのテンプレートサイズが(1×1)の時,位置重みの無いバイラテラルフィルタとなります.
数式等の詳細を図式注釈に埋め込みました.詳細が知りたい方はそこを参照してください.
(4)結果およびまとめ
画質評価の指標であるPSNRを計測すると,フィルタなし 28.0 dB,ガウシアン 30.5 dB,メディアン 32.8 dB,バイラテラル 33.6 dB,ノンローカル 35.3 dB となりました.
大きな画質改善がみられるメディアン,バイラテラル,ノンローカルの各手法で,強さを変えての画像にノイズを付加した画像をノイズ除去を行った結果が下記グラフです.
ノンローカルは最もノイズ除去効果が高く,特にノイズが大きいときにバイラテラルより効果的なことがわかります.図に示す画像からも効果がよくわかります.
また計算時間は,
メディアン 0.8ms,
ガウシアン 3.5ms,
バイラテラル 103ms,
ノンローカル 524ms(並列化なし),128ms(並列化あり)(※バグ修正&コード最適化前は並列化なしで684ms)
となり,このフィルタの計算時間が非常に大きいことがわかります.しかしこれは安直な実装であり,下記論文などのいくつかの高速化手法も提案されています.なお,実験環境はCore i7 2.93GHzで行いました.
J. Wang, Y. Guo, Y. Ying, Y. Liu, Q. Peng, “Fast Non-Local Algorithm for Image Denoising,” in Proc. IEEE International Conference on Image Processing 2006 (ICIP2006), pp. 1429 – 1432, Oct. 2006.
下記画像は左上段(入力画像),右上段(ノイズ付加画像),左中段(ガウシアンフィルタ),右中段(メディアンフィルタ),左下段(バイラテラルフィルタ),右下段(Non-local means Filter)となっています.
ありがとうございます.テストした結果上記指摘で動作します.
コードの修正を行いました.と同時にコードの最適化をしてしまったので,修正部分が変わってしまいました.大体速度が1.2倍くらいになっています.
サンプルコードにバグがあるようです。
行数 172, 173, 242, 243
検索点はテンプレートの中心と見なさなければならないはずですが、
そうなっていませんでした。下記に修正コードを示します。
修正前:
uchar* s = im.ptr(bbj+l+n); s+=(bbi+k);
uchar* t = im.ptr(bbj+n);t+=(bbi);
修正後:
uchar* s = im.ptr(bbj+l+n); s+=(bbi+k-tr);
uchar* t = im.ptr(bbj+n);t+=(bbi-tr);
English message. It translated. I’m sorry.
Sample sauce had a bug.
Although it considered that a searching point was the center of a template, it had not become so.
A correction code is shown below.
line 172, 173, 242, 243
before:
uchar* s = im.ptr(bbj+l+n); s+=(bbi+k);
uchar* t = im.ptr(bbj+n);t+=(bbi);
after:
uchar* s = im.ptr(bbj+l+n); s+=(bbi+k-tr);
uchar* t = im.ptr(bbj+n);t+=(bbi-tr);