Python版OpenCVで非局所的平均フィルタ(NLM Filter)を実装し、画像のノイズを除去する方法をソースコード付きで解説します。
非局所的平均フィルタとは
非局所的平均フィルタ (Non-Local Means Filter, NLMフィルタ) は、画像のノイズ除去を行う空間フィルタの1つです。バイラテラルフィルタと同様、輪郭(エッジ)を保持しながらノイズを除去できる特徴があります。
非局所的平均フィルタは、各画素に対して、類似する画素の重み付き平均を計算してノイズを除去します。原理については、以下ページで別途解説しています。

今回は、Python版OpenCVを用いて非局所的平均フィルタを実装し、画像のノイズを除去する方法を解説します。
サンプルコード① cv2.bilateralFilterで実装
OpenCVのcv2.bilateralFilterで実装した例です。
実行結果
以下は、天体写真(オリオン大星雲、M42)に対してサンプルプログラムを実行した結果です。
■入力画像(左)と出力画像(右)
背景ノイズを除去しつつ、星雲の輪郭は保持されています。
コード解説
以下の部分で画像imgにフィルタを適用し、フィルタ処理された画像をfilteredという変数に保存しています。
filtered = cv.fastNlMeansDenoisingColored(img, None, h, ForColorComponents, templateWindowSize, searchWindowSize)
パラメータ | 説明 |
---|---|
src |
入力画像。 |
filtered |
出力画像。入力画像と同じサイズと型を持つ。 |
h |
フィルタの強さ。値が大きいほどノイズ除去効果が強くなるが、輪郭も失われやすい。 |
hForColorComponents |
カラーフィルタの強さ。値が大きいほどカラーノイズ除去効果が強くなる。 |
templateWindowSize |
部分画像ウのサイズ。デフォルトは7。 |
searchWindowSize |
探索窓のサイズ。デフォルトは21。 |
サンプルコード② パラメータをスライドバーで調整
以下は、フィルタのパラメータをスライドバーで調整し、リアルタイムで処理結果を表示するサンプルプログラムです。画像によって最適なパラメータは異なるため、このようにさまざまな設定を試してみると良いでしょう。
実行結果
以下は、天体写真(オリオン大星雲、M42)に対してサンプルプログラムを実行した結果です。
コード解説
以下のupdate
関数は、トラックバーの位置に基づいてフィルタのパラメータを取得し、フィルタを適用します。この関数が呼び出されるたびにフィルタが更新され、画像が再表示されます。
def update(val):
# トラックバーの位置に基づいてパラメータを取得
d = cv.getTrackbarPos('d', 'Bilateral Filter')
sigmaColor = cv.getTrackbarPos('sigmaColor', 'Bilateral Filter')
sigmaSpace = cv.getTrackbarPos('sigmaSpace', 'Bilateral Filter')
# フィルタを適用
filtered = cv.fastNlMeansDenoisingColored(img, None, h, hForColor, templateWindowSize, searchWindowSize)
# フィルタ処理後の画像を表示
cv.imshow('Bilateral Filter', filtered)
以下で新しいウィンドウを作成し、3つのトラックバーを追加します。トラックバーはそれぞれd
、sigmaColor
、sigmaSpace
のパラメータを調整するためのものです。
# ウィンドウを作成
cv.namedWindow('Bilateral Filter')
# トラックバーを作成
cv.createTrackbar('d', 'Bilateral Filter', 9, 50, update)
cv.createTrackbar('sigmaColor', 'Bilateral Filter', 75, 200, update)
cv.createTrackbar('sigmaSpace', 'Bilateral Filter', 75, 200, update)
createTrackbarについても引数の役割を簡単に解説します。
cv.createTrackbar('h', 'Non-Local Means Filter', 10, 50, update)
パラメータ | 説明 |
---|---|
d | ラックバーのラベル(名前)を指定します。このラベルはトラックバーの識別に使用されます。ここでは、h という名前が使われています。 |
10 | トラックバーの初期位置(初期値)を指定します。 |
50 | トラックバーの最大値を指定します。 |
update | トラックバーが変更されたときに呼び出されるコールバック関数を指定します。ここでは、update 関数が指定されています。この関数は、トラックバーの値が変更されるたびに実行され、フィルタのパラメータが更新されます。 |
トラックバーの位置を変更するたびにupdate
関数が呼び出され、トラックバーの新しい位置に基づいてフィルタのパラメータが再計算され、画像に適用されます。
これにより、リアルタイムでh
の値を変更しながらフィルタの効果を確認することができます。他のトラックバーについても同様です。
以下は、初期表示とメインループの部分です。最初にupdate
関数が呼び出され、初期表示が行われます。その後、ユーザーがq
キーを押すまでメインループが実行され続け、ループ内でキー入力を待機します。q
キーが押されると、すべてのウィンドウが閉じられ、プログラムが終了します。
# 初期表示
update(0)
# ユーザーが 'q' キーを押すまで待機
while True:
if cv.waitKey(1) & 0xFF == ord('q'):
break
cv.destroyAllWindows()
関連ページ

コメント