【Python/OpenCV】バイラテラルフィルタ(Bilateral Filter)でノイズ除去

Python版OpenCVでバイラテラルフィルタ(Bilateral Filter)を実装し、画像のノイズを除去する方法をソースコード付きで解説します。

バイラテラルフィルタとは

バイラテラルフィルタ(Bilateral Filter)は、画像の輪郭検出に用いられる空間フィルタの1つです。ノイズ除去を行いつつ輪郭を保持する優れた特性があります。これを実現するために、バイラテラルフィルタは空間的な距離と輝度差の両方に基づいて重み付けを行います。つまり、輝度差の差が大きいところ(輪郭部分)は、フィルタの重みを小さくします。バイラテラルフィルタの原理については、以下ページで別途解説しています。

バイラテラルフィルタの原理・特徴・計算式
画像処理におけるバイラテラルフィルタ(Bilateral Filter)の原理や計算式についてまとめました。

今回は、Python版OpenCVを用いてバイラテラルフィルタを実装し画像のノイズを除去する方法を解説します。

サンプルコード① cv2.bilateralFilterで実装

OpenCVのcv2.bilateralFilterで実装した例です。


実行結果

以下は、天体写真(オリオン大星雲、M42)に対してサンプルプログラムを実行した結果です。

■入力画像(左)と出力画像(右)

背景ノイズを除去しつつ、星雲の輪郭は保持されています。

コード解説

以下の部分で画像imgにバイラテラルフィルタを適用し、フィルタ処理された画像をfilteredという変数に保存しています。

filtered = cv.bilateralFilter(img, d=9, sigmaColor=75, sigmaSpace=75)
パラメータ 説明
d フィルタを適用する画素の範囲を直径で指定します。値を大きくするほどノイズ除去の効果が大きくなります。
sigmaColor 画素値の変化量に基づく重み付けを計算する際の空間フィルタの標準偏差。値を大きくするほど、ノイズ除去効果が大きくなります。(輪郭もぼけやすくなる)
sigmaSpace 画素の距離に基づく重み付けを計算する際の空間フィルタの標準偏差。値を大きくするほど、広範囲の画素の距離を考慮して重み付けを行い、フィルタの効果が強くなります。

サンプルコード② パラメータをスライドバーで調整

以下は、バイラテラルフィルタのパラメータをスライドバーで調整し、リアルタイムで処理結果を表示するサンプルプログラムです。


実行結果

以下は、天体写真(オリオン大星雲、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.bilateralFilter(img, d, sigmaColor, sigmaSpace)

    # フィルタ処理後の画像を表示
    cv.imshow('Bilateral Filter', filtered)

以下で新しいウィンドウを作成し、3つのトラックバーを追加します。トラックバーはそれぞれdsigmaColorsigmaSpaceのパラメータを調整するためのものです。

# ウィンドウを作成
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('d', 'Bilateral Filter', 9, 50, update)
パラメータ 説明
d ラックバーのラベル(名前)を指定します。このラベルはトラックバーの識別に使用されます。ここでは、dという名前が使われています。
9 トラックバーの初期位置(初期値)を指定します。この場合、トラックバーの初期位置は9です。
50 トラックバーの最大値を指定します。この場合、トラックバーの範囲は0から50までになります。
update トラックバーが変更されたときに呼び出されるコールバック関数を指定します。ここでは、update関数が指定されています。この関数は、トラックバーの値が変更されるたびに実行され、フィルタのパラメータが更新されます。

トラックバーの位置を変更するたびにupdate関数が呼び出され、トラックバーの新しい位置に基づいてバイラテラルフィルタのパラメータが再計算され、画像に適用されます。
これにより、リアルタイムでdの値を変更しながらフィルタの効果を確認することができます。sigmaColorやsigmaSpaceのトラックバーについても同様です。

以下は、初期表示とメインループの部分です。最初にupdate関数が呼び出され、初期表示が行われます。その後、ユーザーがqキーを押すまでメインループが実行され続け、ループ内でキー入力を待機します。qキーが押されると、すべてのウィンドウが閉じられ、プログラムが終了します。

# 初期表示
update(0)

# ユーザーが 'q' キーを押すまで待機
while True:
    if cv.waitKey(1) & 0xFF == ord('q'):
        break

cv.destroyAllWindows()

関連ページ

【Python版OpenCV入門】画像処理の基礎〜応用例までサンプルコード付きで徹底解説
Python版OpenCVで画像処理プログラミングを行う方法を入門者向けにソースコード付きで解説するページです。
この記事を書いた人
西住技研

Python使用歴10年以上。研究、仕事、趣味でデータ分析や作業自動化などに活用してきたノウハウを情報発信しています。
詳しいプロフィールやお問合せはこちらのページまで。
YoutubeX(旧Twitter)でも情報発信中です!

西住技研をフォローする
OpenCV

コメント