cv::blur の使い方【OpenCV/C++】〜平均化フィルタで画像を平滑化する〜

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

cv::blur の使い方【OpenCV/C++】〜平均化フィルタで画像を平滑化する〜

cv::blur は、指定したカーネルサイズの平均化フィルタ(ボックスフィルタ)を画像に適用する関数です。近傍ピクセルの平素値で各画素を置き換えるため、単純なノイズ除去やぼかしに使います。

最小の呼び出しはこれだけです。

cv::blur(src, dst, cv::Size(5, 5));

動作環境

  • OpenCV 4.x
  • コンパイル例: g++ -std=c++17 main.cpp $(pkg-config --cflags --libs opencv4) -o main

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


基本の使い方

#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    // 画像を読み込む(グレースケールでも BGR でも可)
    cv::Mat src = cv::imread("input.jpg");
    if (src.empty()) {
        std::cerr << "画像を読み込めませんでした" << std::endl;
        return 1;
    }

    cv::Mat dst;

    // 5×5 の平均化フィルタを適用
    cv::blur(src, dst, cv::Size(5, 5));

    // 結果を保存
    cv::imwrite("output.jpg", dst);
    std::cout << "保存しました: output.jpg" << std::endl;

    return 0;
}

実行結果:

保存しました: output.jpg

output.jpg を開くと、元画像より全体的にぼけた(平滑化された)画像が確認できます。カーネルサイズを大きくするほどぼけが強くなります。

コードのポイント

  • cv::imread 直後に empty() で読み込み失敗を確認します。パス間違いやファイル不在は実行時エラーではなく空 Mat として返るため、必須のチェックです。
  • cv::blur は入力と同じ型・サイズの Matdst に出力します。dst の事前初期化は不要です。
  • BGR・グレースケールどちらの画像にも適用できます。

引数と戻り値

引数 説明
src cv::InputArray 入力画像。チャンネル数・深度は問わない
dst cv::OutputArray 出力画像。src と同サイズ・同型
ksize cv::Size カーネルサイズ(幅・高さ)。奇数でなくてもよい
anchor cv::Point アンカー位置。cv::Point(-1,-1) でカーネル中心(デフォルト)
borderType int 境界補完の方法。cv::BORDER_DEFAULT が通常の選択(デフォルト)

戻り値は void です。結果は dst に書き込まれます。

ksizecv::Size(1, 1) を渡すと処理なし(コピー)になります。奇数サイズが推奨されますが偶数も動作します。


実践例

実践例 1: カーネルサイズを変えて比較する

実務ではカーネルサイズをパラメータとして持ち、強度を調整することが多いです。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>

int main() {
    cv::Mat src = cv::imread("input.jpg");
    if (src.empty()) {
        std::cerr << "画像を読み込めませんでした" << std::endl;
        return 1;
    }

    // 複数カーネルサイズで出力を比較
    std::vector<int> sizes = {3, 9, 21};
    for (int k : sizes) {
        cv::Mat dst;
        cv::blur(src, dst, cv::Size(k, k));

        std::string filename = "blur_" + std::to_string(k) + ".jpg";
        cv::imwrite(filename, dst);
        std::cout << "保存: " << filename << std::endl;
    }

    return 0;
}

実行結果:

保存: blur_3.jpg
保存: blur_9.jpg
保存: blur_21.jpg

カーネルサイズ 3 は軽微なぼけ、9 は中程度、21 では輪郭がかなり失われた強いぼかしになります。


実践例 2: 前処理として二値化の前に適用する

実務でよくあるのが、ノイズ除去を目的として二値化の直前に平均化フィルタをかける用途です。cv::blur を事前に適用することで、孤立したノイズ画素が平均化されてなだらかになり、二値化後のノイズが減ります。

#include <opencv2/opencv.hpp>
#include <iostream>

int main() {
    // グレースケールで読み込む
    cv::Mat src = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);
    if (src.empty()) {
        std::cerr << "画像を読み込めませんでした" << std::endl;
        return 1;
    }

    // 平均化フィルタでノイズを平滑化
    cv::Mat blurred;
    cv::blur(src, blurred, cv::Size(5, 5));

    // 大津の方法で二値化
    cv::Mat binary;
    cv::threshold(blurred, binary, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);

    cv::imwrite("binary.jpg", binary);
    std::cout << "二値化画像を保存しました: binary.jpg" << std::endl;

    return 0;
}

実行結果:

二値化画像を保存しました: binary.jpg

cv::threshold の詳細は cv::threshold の使い方【OpenCV/C++】〜二値化と大津の方法〜 を参照してください。


つまずきポイント

⚠️ カーネルサイズを偶数にしても動くが、結果がずれることがある

cv::blur はカーネルサイズに偶数を受け付けますが、アンカーがカーネル中心(デフォルト)のとき、偶数サイズだとアンカー位置が整数にならず意図しない方向のオフセットが生じる場合があります。特別な理由がない限り、カーネルサイズは奇数(3, 5, 7…)を使うのが安全です。

⚠️ 入力の深度が CV_32F のとき、出力型に注意

cv::blur は入力画像の深度を保持して出力します。float 型(CV_32F)の Mat を渡すと出力も float になります。その後 cv::imwrite で保存しようとすると、CV_8U 型でないとして assertion で落ちます。保存前に convertToCV_8U に変換してください。

dst.convertTo(dst_8u, CV_8U);

⚠️ imread が空 Mat を返す

実行時カレントディレクトリが IDE のプロジェクトフォルダではなくビルド出力フォルダになっているケースが多く、相対パスが通らないことがあります。空 Mat チェック(src.empty())を必ず入れ、パスは絶対パスで確認するのが確実です。日本語を含むパスも cv::imread で読めない環境があるため注意してください。


関連する関数

平均化フィルタ以外の平滑化フィルタも合わせて把握しておくと、用途に応じて使い分けができます。


まとめ

cv::blur は近傍ピクセルの平均値で各画素を置き換えるシンプルな平滑化フィルタです。カーネルサイズ(cv::Size)を大きくするほどぼけが強くなります。ノイズ除去・前処理用途で手軽に使える一方、エッジが失われる点を理解した上で、GaussianBlur や medianBlur と使い分けるのが実務でのポイントです。

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

本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/API(C++製・OpenCV 4.10)を開発しています。顔認証システムへの組み込み実績多数。

→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

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