OpenCV

【C++】OpenCV画像平滑化:平均化、ガウシアン、中央値、バイラテラルフィルタでノイズ除去技術を実現する方法

C++とOpenCVを使うと、平均化、ガウシアン、中央値、バイラテラルなどの各フィルタで画像の平滑化が実現でき、ノイズを抑えながら柔らかいぼかし効果が得られるため、直感的に画像処理を楽しむことができます。

平均化フィルタ

アルゴリズムの概要

平均化フィルタは、画像の各画素の周囲にある画素の平均値を計算して、画像全体をソフトにぼかす方法です。

ノイズの影響を和らげ、細かいディテールをぼかす効果が期待できるため、画像処理の前処理などで重宝されます。

平均化フィルタは、重みづけなしに単純平均を出すので、計算負荷が低めな点も魅力です。

パラメータ設定

平滑化処理を行う際のパラメータ設定は、フィルタ効果に大きく影響します。

特にカーネルサイズは、ぼかしの範囲や強さに直結するため、適切な値を選ぶことが重要です。

以下のサンプルコードは、cv::blur()関数を用いた平均化フィルタの実装例です。

#include <opencv2/opencv.hpp>
int main() {
    // 画像の読み込み
    cv::Mat inputImage = cv::imread("image.jpg");
    if(inputImage.empty()){
        std::cerr << "画像の読み込みに失敗しました" << std::endl;
        return -1;
    }
    // 5x5サイズの平均化フィルタを適用
    cv::Mat outputImage;
    cv::blur(inputImage, outputImage, cv::Size(5, 5));
    // 結果の表示
    cv::imshow("Original Image", inputImage);
    cv::imshow("Blurred Image", outputImage);
    cv::waitKey(0);
    return 0;
}
[画像ウィンドウに「Original Image」と「Blurred Image」がそれぞれ表示される]

カーネルサイズの影響

カーネルサイズは、ぼかしの強さや範囲に直接関わるため、選定に慎重な検討が必要です。

カーネルサイズを大きくすると、広い範囲の画素の平均が反映され、画像全体がより柔らかくぼやける効果が得られます。

一方、小さいサイズの場合は、局所的なぼかし効果が得られるため、細部をより保つことが可能です。

また、カーネルサイズが奇数で設定されると、フィルタの中心が明確になり、対称性が保たれるため、一般的には奇数が推奨されます。

適用時の留意点

平均化フィルタは、エッジ部がぼやけやすくなる特徴があります。

エッジが重要な画像の場合は、エッジ保持が必要な手法との併用や、ほかの平滑化フィルタと組み合わせるなどの工夫が求められます。

また、各画素に対して均等な重み付けを行うため、特徴的なディテールが失われる可能性も考慮する必要があります。

ガウシアンフィルタ

原理と計算方法

ガウシアンフィルタは、ガウス分布に基づいた重み付けを行い、各画素の近傍情報の加重平均を取得する手法です。

ガウス分布を利用するため、中心に近い画素ほど重みが大きく、離れるにつれて小さな重みが割り当てられます。

これにより、エッジ部の保護がしやすく、自然なぼかし効果が得られるのが特徴です。

計算は、以下の式に従って実施されます。

G(x,y)=12πσ2exp(x2+y22σ2)

ここで、σは標準偏差で、ぼかしの広がりに影響を与えます。

パラメータ設計

ガウシアンフィルタの効果を最大限に引き出すためには、カーネルサイズと標準偏差の組み合わせが重要です。

カーネルサイズが小さすぎると、ガウス分布がうまく表現されず、ぼかし効果が限定的になります。

反対に、大きすぎると画像全体が過度にぼやける可能性があります。

そのため、状況に応じたパラメータの調整が求められます。

カーネルサイズと標準偏差の関係

カーネルサイズと標準偏差は密接に関係しており、一般的にカーネルサイズはσの約6σ+1程度の大きさに設定されると良い結果が得られると言われています。

これにより、ガウス分布の両端まで十分にカバーでき、滑らかな処理が可能になります。

以下は、ガウシアンフィルタの適用例です。

#include <opencv2/opencv.hpp>
int main() {
    // 画像の読み込み
    cv::Mat inputImage = cv::imread("image.jpg");
    if(inputImage.empty()){
        std::cerr << "画像の読み込みに失敗しました" << std::endl;
        return -1;
    }
    // 5x5のカーネルサイズでガウシアンフィルタを適用、sigmaは自動設定
    cv::Mat outputImage;
    cv::GaussianBlur(inputImage, outputImage, cv::Size(5, 5), 0);
    // 結果の表示
    cv::imshow("Original Image", inputImage);
    cv::imshow("Gaussian Blurred Image", outputImage);
    cv::waitKey(0);
    return 0;
}
[「Original Image」と「Gaussian Blurred Image」のウィンドウが表示される]

適用条件と選定基準

ガウシアンフィルタは、画像のエッジに対して自然なぼかし効果を出すことが期待されるため、自然画像や風景写真などでよく使用されます。

エッジ付近におけるハードな輪郭を和らげるが、過度なぼかしは避けたい場合に適しています。

また、標準偏差を適切に選ぶことで、ノイズ除去効果とディテール保持のバランスを調整できるため、実際の用途に合わせたパラメータチューニングが大切です。

中央値フィルタ

基本原理

中央値フィルタは、各画素の周囲にある画素値の中央値を求めることでノイズ除去を実現する手法です。

ランダムノイズや「塩胡椒」ノイズ(スパイクノイズ)に対して非常に有効な特性があり、周囲の極端な値が除去されるため、ノイズを自然に低減できます。

エッジの保護に優れている点も魅力です。

調整可能なパラメータ

中央値フィルタでは、カーネルサイズが主要なパラメータとなります。

サンプルとして、カーネルサイズを5に設定することで、周囲5×5範囲の中央値が求められるようになっています。

パラメータの調整によって、ぼかしの強さとエッジの保持力のバランスを実現することが可能です。

適用例と効果の検証

以下は、cv::medianBlur()関数を利用した中央値フィルタの実装例になります。

#include <opencv2/opencv.hpp>
int main() {
    // 画像の読み込み
    cv::Mat inputImage = cv::imread("image.jpg");
    if(inputImage.empty()){
        std::cerr << "画像の読み込みに失敗しました" << std::endl;
        return -1;
    }
    // カーネルサイズ5で中央値フィルタを適用
    cv::Mat outputImage;
    cv::medianBlur(inputImage, outputImage, 5);
    // 結果の表示
    cv::imshow("Original Image", inputImage);
    cv::imshow("Median Blurred Image", outputImage);
    cv::waitKey(0);
    return 0;
}
[2つのウィンドウに「Original Image」と「Median Blurred Image」が表示される]

この例では、ノイズが含まれる場合に、スムーズな画像へと整える効果が確認でき、エッジ部のディテールが維持される様子が見て取れるでしょう。

バイラテラルフィルタ

エッジ保持の仕組み

バイラテラルフィルタは、空間距離と色空間の情報の両方を考慮して平滑化を行うフィルタです。

エッジ部分のディテールを維持しながら、ノイズを削減する効果があるため、エッジ保持を重視する場面で利用されます。

エッジ保持の仕組みは、空間的な近接性と色の類似性を同時に考えることで、エッジに沿った処理を実現する点にあります。

利用時のパラメータ詳細

バイラテラルフィルタの主なパラメータとして、空間距離パラメータと色空間値パラメータが挙げられます。

これらにより、フィルタの動作が大きく左右されます。

空間距離パラメータの影響

空間距離パラメータは、画素の空間的距離に応じた重み付けを行います。

大きな値に設定すると、広い範囲の画素が考慮され、全体的なぼかし効果が増します。

一方で、エッジ部分でのディテール保持が難しくなる場合があります。

色空間値パラメータの影響

色空間値パラメータは、隣接する画素間の色の違いに基づき、重みづけに調整を行います。

値を低く設定すると、色の差異に敏感になり、エッジがシャープに保たれます。

逆に高くすると、色の差異の影響が小さくなり、全体的な平滑化が促進されます。

使用上の注意点

バイラテラルフィルタを使用する場合、パラメータの設定が非常に重要です。

空間距離と色空間値の両方を適切に設定しないと、エッジ部分が不自然に処理されたり、逆にノイズが十分に除去されなかったりする可能性があります。

また、計算負荷がやや高いため、リアルタイム性を求める場合は注意が必要です。

以下は、バイラテラルフィルタの実装例です。

#include <opencv2/opencv.hpp>
int main() {
    // 画像の読み込み
    cv::Mat inputImage = cv::imread("image.jpg");
    if(inputImage.empty()){
        std::cerr << "画像の読み込みに失敗しました" << std::endl;
        return -1;
    }
    // バイラテラルフィルタを適用
    // 9はフィルタの直径、75は色空間値パラメータ、75は空間距離パラメータ
    cv::Mat outputImage;
    cv::bilateralFilter(inputImage, outputImage, 9, 75, 75);
    // 結果の表示
    cv::imshow("Original Image", inputImage);
    cv::imshow("Bilateral Blurred Image", outputImage);
    cv::waitKey(0);
    return 0;
}
[ウィンドウに「Original Image」と「Bilateral Blurred Image」が表示され、エッジが保たれた状態で平滑化されていることを確認]

このコード例では、エッジのディテールがしっかりと維持されつつ、ノイズが効果的に低減される様子を実感できる構成になっているので、フィルタパラメータの調整実験がしやすくなっています。

パフォーマンス評価

処理速度の比較

平滑化フィルタ各種は、計算量やアルゴリズムの複雑さに応じて、処理速度に差が出る可能性があります。

  • 平均化フィルタは、比較的シンプルな演算で済むため、処理速度が速い傾向があります
  • ガウシアンフィルタは、指数関数の計算を含むため、平均化フィルタに比べるとやや遅くなる場合があります
  • 中央値フィルタは、ソート処理が必要となるため、画像サイズやカーネルサイズが大きい場合、実行速度に影響が出ることがあります
  • バイラテラルフィルタは、空間情報と色空間情報を両立させるため、他のフィルタと比較して計算負荷が高くなる場合があります

画像品質への影響

各フィルタは、目的に応じた平滑化効果を提供し、画像の品質に与える影響が異なります。

  • 平均化フィルタは、全体的にソフトなぼかし効果を与えるが、エッジのシャープさが失われやすい
  • ガウシアンフィルタは、エッジ部分をある程度保護しながらぼかすので、自然な仕上がりが期待できます
  • 中央値フィルタは、ノイズやスパイクノイズに対して効果的に働き、エッジをきれいに保ちます
  • バイラテラルフィルタは、エッジのディテールを維持しながらもノイズ除去が可能で、画像品質の保全に優れる

パラメータ最適化

カーネルサイズの選定基準

カーネルサイズは、フィルタの動作に大きく影響するため、対象画像の特性や求めるぼかし具合に応じて選定する必要があります。

  • 小さいカーネルサイズは、細かいディテールを残す効果が期待できるが、微小なノイズが目立つ可能性があります
  • 大きいカーネルサイズは、全体的な平滑化が強くなりノイズが相殺される反面、重要なディテールも失われやすくなります

実践的には、試行錯誤しながら最適なサイズ設定を探索するのがおすすめです。

標準偏差調整のポイント

ガウシアンフィルタなどで用いる標準偏差は、ぼかし効果の広がりに直結します。

  • 低い標準偏差では、中心付近の影響が強く、細かい変化を捉えやすくなるが、ノイズ除去効果は限定的
  • 高い標準偏差は、全体的な平滑化が強くなるが、エッジの保持が難しくなるため、適宜調整が必要となります

数式12πσ2exp(x2+y22σ2)に基づいて、適切なバランスを考えると良いでしょう。

適用ケースの検討

ノイズ種類別のフィルタ選択

画像に含まれるノイズの種類によって、フィルタ選択の基準が変わります。

  • ランダムノイズやブロックノイズの場合は、平均化フィルタやガウシアンフィルタで十分な場合が多い
  • 塩胡椒ノイズなど、極端な値が混入している場合は、中央値フィルタが有効に働きます
  • エッジ保持が重要なシーンでは、バイラテラルフィルタを使うと自然な仕上がりになることが多いです

各フィルタのメリット・デメリット比較

以下の表は、各平滑化フィルタのメリットとデメリットを簡単にまとめたものです。

フィルタメリットデメリット
平均化フィルタ計算量が少なく、処理速度が速いエッジのぼけが大きくなる可能性がある
ガウシアンフィルタエッジ保持と全体的なぼかしのバランスが良い計算負荷がやや高め
中央値フィルタノイズ除去性能が高く、エッジが維持されやすいカーネルサイズによってはディテールまでぼやけることがある
バイラテラルフィルタエッジを残しながらノイズを効果的に除去処理速度が低く、リアルタイム処理には不向きな場合がある

利用上の選定ポイント

画像特性に合わせたフィルタ選択

画像の内容や用途に応じてフィルタを選ぶことで、最適な平滑化効果が得られます。

  • 自然風景や人物画像など、エッジが重要な場合は、ガウシアンフィルタやバイラテラルフィルタが適しています
  • 医療画像や工業用画像では、データの歪みが少ない形でノイズを除去するため、目的に合わせたパラメータ調整が求められます

実際の利用事例による検討ポイント

実際のプロジェクトでは、以下のポイントを考慮してフィルタを選定することが推奨されます。

  • 処理速度の要件と平滑化効果のバランス
  • 画像解像度やノイズレベルに応じたパラメータの自動調整
  • エッジ部分やディテール保持が求められる場合のフィルタ選択
  • 複数のフィルタを組み合わせたハイブリッドアプローチの検討

これらの検討ポイントを踏まえることで、実際のシーンや利用環境に最適な平滑化手法が見つけやすくなります。

まとめ

今回の記事では、C++とOpenCVを使って4種類の画像平滑化フィルタについて詳しく解説しました。

平均化フィルタではシンプルなぼかし効果が得られ、ガウシアンフィルタでは自然な重み付けが活用できます。

中央値フィルタは、特にスパイクノイズの除去やエッジ保持に優れており、バイラテラルフィルタはエッジディテールを大切にしながら総合的なノイズ低減が可能です。

各フィルタのパラメータ設定や調整方法、適用ケースも具体例を交えて説明したので、実際の画像処理タスクで参考になれば嬉しいです。

使用するシーンや画像の特性に合わせて、ベストな選択ができると良いですね。

関連記事

Back to top button
目次へ