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.GaussianBlur — 高速なガウシアンブラー。エッジ保持は不要で速度優先の場合に使う
- Cv2.MedianBlur — ごま塩ノイズに強いメディアンフィルタ
- Cv2.ImWrite の使い方【OpenCV/C#】〜画像をファイルに保存する〜 — 処理結果の保存
- Cv2.CvtColor の使い方【OpenCV/C#】色空間をグレースケール・HSVに変換する — グレースケール変換と組み合わせて使う場面が多い
まとめ
Cv2.BilateralFilter は、エッジを保ちながらノイズを除去したい場面で強力な選択肢です。sigmaColor と sigmaSpace の組み合わせで平滑化の強さを制御でき、グレースケール・カラー両対応です。処理コストが高いため、d の値はパフォーマンスを確認しながら調整してください。
🛠 画像処理のプロが開発するSDK/API
本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/APIを開発しています。SDK は C#/.NET 8 に正式対応しており、OpenCvSharp を使うプロジェクトからそのまま組み込めます。
→ 顔認証のなりすまし対策 設計チェックリスト(当ブログ)
→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

