Cv2.BilateralFilter の使い方【OpenCV/C#(OpenCvSharp)】バイラテラルフィルタで輪郭を残してぼかす

OpenCV for C#
📌 準備: OpenCV の環境構築がまだの方はこちら → C++ 環境構築ガイド / C#(OpenCvSharp)セットアップ

Cv2.BilateralFilter の使い方【OpenCV/C#(OpenCvSharp)】〜輪郭を残しながらノイズを除去する〜

Cv2.BilateralFilter は、エッジ(輪郭)を保持しながらノイズを除去できるフィルタです。通常のガウシアンブラーは均一にぼかすのに対し、バイラテラルフィルタは 空間的な近さ と 画素値の近さ の両方を考慮するため、エッジをつぶさずに平滑化できます。

最小構成のコード:

Cv2.BilateralFilter(src, dst, d: 9, sigmaColor: 75, sigmaSpace: 75);

動作環境

  • OpenCV 4.x(OpenCvSharp4)
  • .NET 8 コンソールアプリ
  • NuGet: OpenCvSharp4 + OpenCvSharp4.runtime.win(Windows 実行時)

環境構築がまだの方は環境構築ガイドを先にどうぞ。


基本の使い方

using OpenCvSharp;

// 画像を読み込む
using var src = Cv2.ImRead("input.jpg", ImreadModes.Color);
if (src.Empty()) throw new Exception("画像の読み込みに失敗しました");

// 出力 Mat を準備
using var dst = new Mat();

// バイラテラルフィルタを適用
// d=9: フィルタの直径, sigmaColor=75: 色の許容範囲, sigmaSpace=75: 空間の広がり
Cv2.BilateralFilter(src, dst, d: 9, sigmaColor: 75, sigmaSpace: 75);

// 結果を保存
Cv2.ImWrite("output.jpg", dst);

Console.WriteLine("完了: output.jpg に保存しました");

実行すると、output.jpg にエッジを残したまま平滑化された画像が保存されます。

各行の解説

行 説明
Cv2.ImRead ファイルから画像を読み込む
using var dst = new Mat() 出力用の Mat を確保。using で確実に解放
Cv2.BilateralFilter バイラテラルフィルタ本体。src と dst は同一 Mat 不可
Cv2.ImWrite フィルタ結果をファイルに保存

引数と戻り値

void Cv2.BilateralFilter(
    InputArray  src,
    OutputArray dst,
    int         d,
    double      sigmaColor,
    double      sigmaSpace,
    BorderTypes borderType = BorderTypes.Default
)
引数 型 説明
src InputArray 入力画像(8ビット または 32ビット浮動小数点)
dst OutputArray 出力画像(src と同サイズ・同チャンネル)
d int フィルタ処理に使う近傍ピクセルの直径。-1 を指定すると sigmaSpace から自動計算される
sigmaColor double 色空間のシグマ値。大きいほど色の差異を無視して平滑化する
sigmaSpace double 空間のシグマ値。大きいほど遠いピクセルも影響させる
borderType BorderTypes 境界処理の方法。通常はデフォルトのまま

戻り値: なし(結果は dst に書き込まれる)

sigmaColor と sigmaSpace の目安

用途 sigmaColor sigmaSpace
軽めのノイズ除去 25〜50 25〜50
標準的な平滑化 75 75
強めに平滑化(アニメ調) 150 150

実践例

例1: グレースケール画像に適用する

バイラテラルフィルタはグレースケール画像にも対応しています。グレースケール変換については Cv2.CvtColor の使い方 も参照してください。

using OpenCvSharp;

using var src = Cv2.ImRead("input.jpg", ImreadModes.Color);
if (src.Empty()) throw new Exception("画像の読み込みに失敗しました");

// グレースケールに変換してからフィルタを適用
using var gray = new Mat();
using var dst  = new Mat();

Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
Cv2.BilateralFilter(gray, dst, d: 9, sigmaColor: 75, sigmaSpace: 75);

Cv2.ImWrite("output_gray.jpg", dst);
Console.WriteLine("グレースケール版を保存しました");

例2: d=-1 で sigmaSpace から直径を自動決定する

処理範囲を固定せず sigmaSpace に任せる場合、d=-1 を指定するのが定石です。リアルタイム処理には向きませんが、パラメータ調整がシンプルになります。

using OpenCvSharp;

using var src = Cv2.ImRead("input.jpg", ImreadModes.Color);
if (src.Empty()) throw new Exception("画像の読み込みに失敗しました");

using var dst = new Mat();

// d=-1 で sigmaSpace から直径を自動計算
Cv2.BilateralFilter(src, dst, d: -1, sigmaColor: 75, sigmaSpace: 10);

Cv2.ImWrite("output_auto.jpg", dst);
Console.WriteLine("自動直径版を保存しました");

⚠️ d を大きくすると処理が非常に重くなります。リアルタイム処理では d=5 以下に抑えるか、代替として Cv2.GaussianBlur を検討してください。


つまずきポイント

⚠️ src と dst に同じ Mat を渡すと例外が出る

Cv2.BilateralFilter はインプレース処理(src == dst)に対応していません。必ず別の Mat を用意してください。

// NG: 同じ Mat を渡すと例外
Cv2.BilateralFilter(mat, mat, 9, 75, 75);

// OK: 別の Mat に出力する
using var dst = new Mat();
Cv2.BilateralFilter(mat, dst, 9, 75, 75);

⚠️ d を大きくすると処理が極端に遅くなる

d=15 以上は処理時間が急増します(計算量が直径の2乗に比例するため)。高品質が必要なバッチ処理では問題ありませんが、リアルタイム用途では d=5〜9 を上限の目安にしてください。

⚠️ 入力画像が 16ビット整数型だと動作しない

Cv2.BilateralFilter が受け付けるのは CV_8U(8ビット)または CV_32F(32ビット浮動小数点)です。16ビット画像(CV_16U)をそのまま渡すと例外になります。事前に ConvertTo で型変換してください。

// 16ビット → 8ビットに変換してから渡す
src.ConvertTo(src8u, MatType.CV_8UC3, 1.0 / 256);

関連する関数


まとめ

Cv2.BilateralFilter は、エッジを保ちながらノイズを除去したい場面で強力な選択肢です。sigmaColor と sigmaSpace の組み合わせで平滑化の強さを制御でき、グレースケール・カラー両対応です。処理コストが高いため、d の値はパフォーマンスを確認しながら調整してください。

🛠 画像処理のプロが開発するSDK/API

本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/APIを開発しています。SDK は C#/.NET 8 に正式対応しており、OpenCvSharp を使うプロジェクトからそのまま組み込めます。

→ 顔認証のなりすまし対策 設計チェックリスト(当ブログ)
→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

タイトルとURLをコピーしました