ノイズ除去フィルター「BM3D」を使ってみた
【Pythonコード掲載・NLMフィルターとの比較あり】

Image Processing

こんにちは、てつをです。前回の記事では、NLMフィルターの前後で開発されたフィルターを色々と見ていきました。そして、NLMフィルターの後に開発されたものも様々存在していることがわかってきました。今回は、NLMフィルターが開発されて割とすぐに開発されたBM3Dについて勉強していきたいと思います。NLMフィルターを実際に実行してみた時と同様に、実際のPythonのサンプルコードもございますのでぜひお手元でご利用ください。

目次

  1. BM3Dの概要
  2. BM3Dの実行(サンプルコード掲載)
  3. NLMフィルター vs BM3D

BM3Dの概要

BM3D(Block-Matching and 3D Filtering)は、画像ノイズ除去の分野で広く用いられている高度なアルゴリズムの一つです。この手法は、2007年に発表された論文「Image denoising by sparse 3D transform-domain collaborative filtering」で提案され、特にガウスノイズの除去において非常に高い性能を発揮します。

BM3Dは、ノイズ除去を行うために以下の2つのステージで処理を進めます:

  1. ブロックマッチングとグループ化
    画像内の類似したパッチ(小領域)を探索し、それらを3次元のグループとしてまとめます。このステップにより、異なる場所に存在する類似パターンを抽出し、ノイズを除去しながら情報を統合する準備を整えます。
  2. 3D変換としきい値処理
    グループ化された3次元データに対し、ウェーブレット変換やハードスレッショルディングを適用してノイズを除去します。その後、逆変換を行い、画像に戻します。この処理を2回繰り返すことで、細部をより滑らかに仕上げます。

BM3Dの特長は、単なる局所的な処理ではなく、画像全体から類似する領域を見つけ出して処理する「非局所性」にあります。これにより、画像のエッジや細かいテクスチャを保持しつつ、高精度なノイズ除去が可能となります。余談とはなりますが、ZEISSのYouTubeチャンネルにアップされている動画の説明がわかりやすかったので参考として載せておきます。

また、BM3Dは高度なアルゴリズムであるため、計算コストが高くなるというデメリットもあります。しかし、その分得られる結果は非常に高品質であり、医療画像処理や天体写真など、精度が重視される分野で広く採用されています。

BM3Dが登場した背景

画像のノイズ除去は、デジタル画像処理において長年の課題でした。従来の方法としては、局所的な平均化やメディアンフィルターといった単純な手法が主流でしたが、これらの方法はノイズとともにエッジや細部も損なうため、画像のシャープさが低下するという欠点がありました。

次に登場したのが、NLM(Non-Local Means)フィルターのような非局所的な手法です。NLMは、画像内の類似するピクセルを探索し、その情報を活用してノイズを除去します。この手法はエッジの保持に優れ、より自然な画像を生成できる点で画期的でした。しかし、テクスチャが複雑な画像やノイズレベルが高い場合には限界がありました。

BM3Dは、このNLMをさらに進化させた手法として登場しました。特に、画像内の類似するパッチをブロックマッチングによって検出し、3次元空間で処理するという新しいアプローチを導入しました。この革新的な設計により、エッジや細部を損なうことなくノイズを除去できるという大きな進歩を遂げました。

BM3Dの応用分野

BM3Dの優れた性能は、以下のような分野で活用されています。

  • 医療画像処理
    医療画像(CTやMRIなど)はノイズが多く含まれることがあり、診断に影響を与える可能性があります。BM3Dは、画像のディテールを保持しながらノイズを除去するため、医療分野で高く評価されています。
  • 天文学
    天体観測画像は、撮影条件やセンサーの特性によりノイズが入りやすいです。BM3Dは、微細な星雲や銀河の構造を損なうことなくノイズを取り除くのに役立っています。
  • ビデオ処理
    動画フレームに対してもBM3Dを応用することで、フレーム間の連続性を維持しながらノイズを除去することができます。これは、監視カメラや映画制作などの分野で有用です。
  • デジタル写真
    暗所や高ISO感度で撮影された写真に生じるガウスノイズを効果的に除去します。

他のノイズ除去手法との簡単な違い

BM3Dは、特にNLMと比較されることが多いですが、それ以外の手法とも以下のような違いがあります。

  • 局所フィルター(例: 平均化フィルター、メディアンフィルター)
    単純な数値計算でノイズを除去。欠点としては、エッジや細部もぼかしてしまう点があります。BM3Dはノイズと詳細情報を分離し、細部を保持するのが特徴です。
  • NLM(Non-Local Means)
    非局所的な類似ピクセルを探索してノイズ除去を行いますが、テクスチャが複雑な場合に性能が低下することがあります。BM3Dは類似パッチを3次元空間で処理することで、より精度の高い結果を実現します。
  • ディープラーニングベースの手法
    学習データを基にノイズ除去モデルを構築しますが、大量のトレーニングデータや計算リソースが必要です。BM3Dは事前学習不要で計算リソースが少なくて済むという利点があります。
  • 小波変換ベースの手法
    小波変換を利用してノイズを分離しますが、BM3Dは小波変換だけでなく類似パッチのグループ化も活用するため、より詳細な構造を保持します。

BM3Dは、精度と汎用性の高さからノイズ除去における「ゴールドスタンダード」とされています。ただし、計算コストが高いため、用途に応じて他の手法と使い分けることが重要です。

BM3Dの実行(サンプルコード掲載)

では、実際に自分の手を動かしてBM3Dの機能を確認していきたいと思います。NMLフィルターの時はOpenCVを利用しましたが、ざっと調べてみたところOpenCVでBM3Dの機能の使い方がわからなかったので、今回は別のモジュールbm3dを利用しました。

サンプルの画像はNLMフィルターの検証時と同様にこちらのサイトから取得しています。リチウムイオン電池の正極のSEM画像になります。早速サンプルコードを以下に掲載いたします。

import cv2 as cv
import pybm3d
import matplotlib.pyplot as plt
# 画像読み込み(グレースケール)
img = cv.imread('CathodeFIB-SEM.tif', cv.IMREAD_GRAYSCALE)
img_normalized = img.astype('float32') / 255.0
# BM3Dノイズ除去
sigma_psd = 0.1  # ノイズの標準偏差
denoised_img = pybm3d.bm3d.bm3d(img_normalized, sigma_psd) 

以上で、BM3Dのノイズ除去が実行されています。あとは、実行結果を表示するだけになりますので表示してみましょう。

# 結果表示
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.title("Original")
plt.imshow(img, cmap='gray')
plt.axis('off')

plt.subplot(1, 2, 2)
plt.title("BM3D Denoised")
plt.imshow(denoised_img, cmap='gray')
plt.axis('off')

plt.tight_layout()
plt.show()

上記を実行すると、以下のように元々のオリジナル画像が左に、BM3Dの実行結果が右に表示されます。

輪郭はしっかりと残りつつ、細かなざらつき・ノイズは取り除かれていることが確認できるかと思います。

NLMフィルター vs BM3D

最後に、NLMフィルターとBM3Dの比較をしてみたいと思います。

 NLM_denoised_image = cv2.fastNlMeansDenoising(img, dst=None, h=10, templateWindowSize=7, searchWindowSize=21) 

NLMフィルターは上記の1行を追加で実行してあげれば完了です。では、オリジナル画像、NLMフィルター適用後、BM3D適用後の3つの画像を並べて表示してみたいと思います。

# 結果表示
plt.figure(figsize=(10, 5))
plt.subplot(1, 3, 1)
plt.title("Original")
plt.imshow(img, cmap='gray')
plt.axis('off')

plt.subplot(1, 3, 2)
plt.title("NLM Denoised")
plt.imshow(NLM_denoised_image, cmap='gray')
plt.axis('off')

plt.subplot(1, 3, 3)
plt.title("BM3D Denoised")
plt.imshow(denoised_img, cmap='gray')
plt.axis('off')

plt.tight_layout()
plt.show()

結果としては、NLMフィルターは大きな縦線のノイズも含めて平滑化しており、一方でBM3Dは縦線は残してその他の表面のざらつきは取り除いているような結果となりました。冒頭で述べたように、より細かいところまでを保持しつつノイズを取り除きたい場合はBM3Dの方が適していそうですが、細かいところは置いておいて大きなノイズも含めて取り除きたい場合はNMLフィルターの方が適してそうです。どちらを使うかは状況に応じてユーザーが使い分けていく必要がありそうだと感じました!

今回の検証は以上です。次回は、BM3Dのさらに2年後に出てきたLSSC (Learning-based Sparse Coding)についての調査と、並行して画像のノイズについても調べてみたいと思います。

以上