cv::bilateralFilter の使い方【OpenCV/C++】〜エッジを保ちながらノイズを除去するバイラテラルフィルタ〜
cv::bilateralFilter は、エッジを保持しながらノイズを除去できるフィルタです。ガウシアンフィルタと異なり、輝度差が大きいピクセル(=エッジ付近)には平滑化をかけないため、輪郭がぼけません。最小限の呼び出しは次のとおりです。
cv::bilateralFilter(src, dst, 9, 75, 75);
動作環境
- OpenCV 4.x
- C++17
- ビルド例:
g++ -std=c++17 main.cpp $(pkg-config --cflags --libs opencv4)
環境構築がまだの方は環境構築ガイドを先にどうぞ。
基本の使い方
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
// 画像を読み込む
cv::Mat src = cv::imread("input.png");
if (src.empty()) {
std::cerr << "画像を読み込めませんでした。" << std::endl;
return -1;
}
cv::Mat dst;
// バイラテラルフィルタを適用
// d=9: フィルタ径, sigmaColor=75: 色空間の標準偏差, sigmaSpace=75: 座標空間の標準偏差
cv::bilateralFilter(src, dst, 9, 75, 75);
// 結果を保存
cv::imwrite("output.png", dst);
std::cout << "完了: output.png に保存しました。" << std::endl;
return 0;
}
実行結果:
完了: output.png に保存しました。
実行すると、エッジが維持されたままノイズが低減された output.png が生成されます。ガウシアンブラーと比べて輪郭線がシャープに残っていることが確認できます。
各行の解説
| 行 | 説明 |
|---|---|
cv::imread("input.png") |
画像を BGR 形式で読み込む |
src.empty() チェック |
ファイルが存在しない・パスが間違っている場合に早期リターン |
cv::bilateralFilter(src, dst, 9, 75, 75) |
本体。後述の引数テーブル参照 |
cv::imwrite("output.png", dst) |
フィルタ後の画像を PNG で保存 |
引数と戻り値
void cv::bilateralFilter(
InputArray src, // 入力画像(8ビット or 浮動小数点、1ch or 3ch)
OutputArray dst, // 出力画像(src と同サイズ・同型)
int d, // フィルタ径(奇数推奨。負値を指定すると sigmaSpace から自動計算)
double sigmaColor, // 色空間の標準偏差(大きいほど色差を許容して平滑化が強まる)
double sigmaSpace, // 座標空間の標準偏差(大きいほど遠いピクセルの影響が増す)
int borderType // ボーダー処理(省略時: BORDER_DEFAULT)
);
| 引数 | 型 | 説明 |
|---|---|---|
src |
InputArray |
入力画像。CV_8UC1 / CV_8UC3 / 浮動小数点型に対応 |
dst |
OutputArray |
出力画像。src と同サイズ・同型で自動確保される |
d |
int |
フィルタリングに使用する近傍ピクセルの直径。-1 で sigmaSpace から自動計算 |
sigmaColor |
double |
色空間の標準偏差。10 程度で弱い平滑化、150 前後で非常に強い平滑化 |
sigmaSpace |
double |
座標空間の標準偏差。d が正の場合は主に d が径を決定する |
borderType |
int |
端部の補完方法。通常はデフォルト(cv::BORDER_DEFAULT)のまま |
d と sigmaSpace の関係
d を -1 にすると sigmaSpace の値から自動的にフィルタ径が決まります。大きな画像でリアルタイム処理する場合は d=5 程度に固定し sigmaSpace を調整する方が処理時間を制御しやすいです。
実践例
例1: グレースケール画像へのノイズ除去
カメラの読み取り画像を二値化する前処理としてバイラテラルフィルタを使うケースです。エッジがぼけると二値化精度が落ちるため、cv::GaussianBlur より有利な場合があります。
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
cv::Mat src = cv::imread("input.png", cv::IMREAD_GRAYSCALE);
if (src.empty()) {
std::cerr << "画像を読み込めませんでした。" << std::endl;
return -1;
}
cv::Mat filtered;
// グレースケール(1ch)もそのまま渡せる
cv::bilateralFilter(src, filtered, 9, 75, 75);
cv::Mat binarized;
// バイラテラルフィルタ後に大津の方法で二値化
cv::threshold(filtered, binarized, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
cv::imwrite("binarized.png", binarized);
std::cout << "二値化完了: binarized.png" << std::endl;
return 0;
}
例2: sigmaColor を変えて平滑化の強さを比較する
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
cv::Mat src = cv::imread("input.png");
if (src.empty()) {
std::cerr << "画像を読み込めませんでした。" << std::endl;
return -1;
}
// sigmaColor を変えた3パターンを保存して比較
for (int sigma : {25, 75, 150}) {
cv::Mat dst;
cv::bilateralFilter(src, dst, 9, static_cast<double>(sigma), 75);
std::string filename = "bilateral_sigma" + std::to_string(sigma) + ".png";
cv::imwrite(filename, dst);
std::cout << "保存: " << filename << std::endl;
}
return 0;
}
実行結果:
保存: bilateral_sigma25.png
保存: bilateral_sigma75.png
保存: bilateral_sigma150.png
sigma=25 はほぼ変化なし、sigma=150 はほぼガウシアンと同等の強い平滑化になります。まず sigma=75 を基準に調整するのが実務上の定石です。
つまずきポイント
⚠️ src と dst に同じ Mat を渡してはいけない
cv::bilateralFilter はインプレース処理(src == dst)をサポートしていません。同じ変数を渡すとアサーションエラーが発生します。
// NG: src と dst が同じ
cv::bilateralFilter(img, img, 9, 75, 75);
// OK: 別の Mat を用意する
cv::Mat result;
cv::bilateralFilter(img, result, 9, 75, 75);
⚠️ 処理速度が遅い
バイラテラルフィルタは計算コストが高く、フィルタ径 d を大きくするほど急激に重くなります。1280×720 の画像で d=15 にすると、cv::GaussianBlur や cv::medianBlur と比べて数倍〜数十倍の時間がかかることがあります(OpenCV 4.x 時点)。リアルタイム処理では d=5〜9 に抑えることを強く推奨します。
⚠️ 浮動小数点入力は正規化範囲に注意
CV_32FC1 / CV_32FC3 の画像を渡す場合、sigmaColor は画素値スケールに合わせて調整が必要です。0〜255 スケールの 8 ビット画像想定で sigmaColor=75 を設定していると、0.0〜1.0 スケールの浮動小数点画像ではフィルタがほぼ効きません(sigmaColor=0.1〜0.3 程度が適切)。
関連する関数
-
cv::GaussianBlur の使い方【OpenCV/C++】〜ガウシアンぼかしで画像を平滑化する〜
エッジ保持は不要で均一に平滑化したい場合はこちら。処理速度も速い。 -
cv::medianBlur の使い方【OpenCV/C++】〜メディアンフィルタで塩胡椒ノイズを除去する〜
ごま塩ノイズ(塩胡椒ノイズ)の除去に特化。バイラテラルフィルタより高速。 -
cv::ximgproc::jointBilateralFilter/cv::ximgproc::bilateralTextureFilter
より高度なバイラテラル系フィルタ。opencv_contribモジュール(ximgproc)に収録。
まとめ
cv::bilateralFilter は、エッジを保持しながらノイズを除去したい場面で第一候補になるフィルタです。d・sigmaColor・sigmaSpace の3パラメータを調整することで平滑化の強さを制御でき、二値化などの前処理に特に有効です。ただし処理コストが高いため、フィルタ径は用途に合わせて最小限に抑えましょう。
🛠 画像処理のプロが開発するSDK/API
本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/API(C++製・OpenCV 4.10)を開発しています。顔認証システムへの組み込み実績多数。

