OpenCV - Canny エッジ検出アルゴリズム

問題の説明

画像セグメンテーションは、デジタル画像を複数のサブ領域に再分割するプロセスであり、コンピューター ビジョン/マシン ビジョンの分野で広く使用されています。その目的は、イメージの表現を単純化または変更して、理解しやすく分析しやすくすることです。一般的な画像セグメンテーション方法には、しきい値処理、クラスタリング、エッジ検出、および領域拡張が含まれます。画像セグメンテーションの問題を解決するには、通常、ドメインの知識を組み合わせて解決効果を向上させる必要があります。

エッジ検出は一般的に使用される画像分割手法であり、画像内の不連続な部分の特徴を抽出することで実現されます。現在、一般的なエッジ検出演算子には、差分演算子、Roberts 演算子、Sobel 演算子、Prewitt 演算子、Log 演算子、および Canny 演算子が含まれます。Canny オペレーターは、1986 年に John F. Canny によって提案されたエッジ検出オペレーターであり、現在最も完全なエッジ検出アルゴリズムの 1 つであると考えられています。一般的に使用される多くの画像処理ツール (MATLAB、OpenCV など) には、Canny オペレーター API が組み込まれています。

キャニーエッジ検出

Canny エッジ検出は、1986 年に John F. Canny によって提案された古典的なエッジ検出アルゴリズムです。画像内のエッジ情報を検出するために、コンピュータービジョンや画像処理の分野で広く使用されています。

用紙情報:

标题:エッジ検出への計算的アプローチ

ジョン・F・キャニー著

出版年: 1986

Canny エッジ検出アルゴリズムの手順

Canny エッジ検出アルゴリズムの目的は、画像内の強いエッジを見つけて、ノイズと弱いエッジを除去しようとすることです。アルゴリズムの手順は次のとおりです。

  1. ノイズ抑制: まず、ガウス フィルターを使用して画像を平滑化し、ノイズの影響を軽減します。

  2. グラデーションの計算: 次に、画像内の各ピクセルのグラデーションの強度と方向を計算します。これは、Sobel などのフィルターを適用することで実現できます。

  3. 非最大抑制: 次に、勾配強度画像に対して非最大抑制を実行して、エッジを洗練し、エッジ応答を除去します。

  4. 二重しきい値: 次に、二重しきい値を使用してエッジの強度を決定します。設定された閾値に従って、エッジ ピクセルは強いエッジ ピクセル、弱いエッジ ピクセル、および非エッジ ピクセルに分類されます。

  5. エッジ接続: 最後に、エッジ接続アルゴリズムを使用して、強いエッジ ピクセルと隣接する弱いエッジ ピクセルを接続し、完全なエッジを形成します。

Canny エッジ検出アルゴリズムは、画像処理の分野で広く評価されており、微妙なエッジを検出でき、ノイズに対する耐性が優れています。

1. ガウス フィルタリングを適用して画像ノイズを除去します。

ガウシアンフィルターは、画像に対して畳み込み演算を行うことで画素値の差を減らし、ノイズの影響を軽減する平滑化フィルターです。

ガウス フィルターのカーネル (またはテンプレート) は 2 次元の重み行列であり、重み値はガウス関数によって計算されます。この重み行列のサイズと標準偏差 (σ) は、ガウス フィルターの 2 つの重要なパラメーターであり、フィルターの滑らかさを決定します。

2 次元のガウス関数は次のように表現できます。

G(x, y) = \frac{1}{2\pi \sigma ^{2}} exp(-\tfrac{x^{2}+y^{2}}{2\sigma ^{2}} )

このうち、G(x,y)は点(x,y)における2次元ガウス関数の値を表し、σは標準偏差を表す。 

画像内の各ピクセルに対して、次の畳み込み演算を使用してガウス フィルターを適用できます。

I' = G * I

このうち、I' はフィルタ処理された画像を表し、G はガウス フィルタ カーネルを表し、I は元の画像を表します。

具体的には、ピクセルごとに、そのピクセルを中心とする近傍でガウス フィルター カーネルを畳み込み、近傍のピクセル値の加重平均をフィルター処理された画像内のピクセルの値として計算します。このように、ガウス フィルターは画像をぼかし、ノイズの影響を軽減します。

ガウス フィルターのサイズと標準偏差は、特定のアプリケーション シナリオに従って選択する必要があることに注意してください。フィルター サイズを大きくし、標準偏差を小さくすると、より強力な平滑化効果が得られますが、エッジ情報がぼやける可能性があります。逆に、フィルター サイズが小さく、標準偏差が大きいと、詳細はより多く保存されますが、ノイズを効果的に抑制できない可能性があります。

2D ガウス フィルターの標準偏差 σ は、フィルターの等方性を保つために水平方向と垂直方向で等しくなります。適切な標準偏差の選択は、ノイズ レベルと画像の特性によって異なります。標準偏差が大きいほど、より強力な平滑化効果が得られますが、エッジや細部がぼやける可能性があります。

 2.  Sobel 演算子を使用してピクセルの勾配を計算します。

Sobel 演算子は、一般的に使用される離散微分演算子であり、画像内の各ピクセルの勾配の強さと方向を計算できます。Canny エッジ検出では、通常、水平方向と垂直方向の画像の勾配を計算するために Sobel オペレーターが使用されます。

グレースケール イメージの場合、次の Sobel 演算子を使用してピクセルの勾配を計算できます。

水平方向の勾配 (Gx):

      -1  0  1
Gx =  -2  0  2
      -1  0  1

垂直方向の勾配 (Gy):

      -1 -2 -1
Gy =   0  0  0
       1  2  1

以下は、Sobel オペレーターを使用してピクセルの勾配を計算する具体的な手順です。

  1. 画像をグレースケールに変換します (グレースケールでない場合)。

  2. 水平方向 (Gx) のソーベル オペレーターと垂直方向 (Gy) のソーベル オペレーターを画像に適用します。

  3. 各ピクセルのグラデーションの強度と方向を計算します。

    G = sqrt(Gx^2 + Gy^2)       (梯度强度)
    θ = arctan(Gy / Gx)         (梯度方向)
    

    このうち、Gは勾配の強さを表し、θは勾配の方向を表す。

このようにして、画像内の各ピクセルの勾配の強さと方向を取得できます。この勾配情報は、Canny エッジ検出アルゴリズムの後続のステップでエッジを検出して接続するために使用されます。

 3. 非最大ピクセル勾配抑制

このステップでは、各ピクセルの勾配方向に隣接するピクセルをチェックし、最大の勾配強度を持つピクセルを保持し、他のピクセルをゼロに抑制する必要があります。

非最大抑制のプロセスをより適切に説明するために、想定される画像の勾配方向を 4 つの主な方向、0° (水平方向)、45° (対角方向)、90° (垂直方向)、および 135° に離散化します。 (斜め方向)。各ピクセルについて、その勾配の強さを、勾配方向に沿って隣接する 2 つのピクセルの勾配の強さと比較します。

ピクセルの勾配方向が 0° (水平方向) の場合、その勾配の強さを、その左右に隣接する 2 つのピクセルの勾配の強さと比較します。

現在のピクセル点が (x, y)、その勾配の方向が 0°、勾配の強さが G(x, y) であるとします。G(x, y) を 2 つの隣接ピクセル、G(x-1, y) および G(x+1, y) の勾配強度と比較します。

  • G(x, y) が 3 つの値のうち最大の場合はそのピクセル値を保持し、それ以外の場合はピクセル値をゼロに抑制します。

具体的には、線形補間を使用してピクセル値を保持するかどうかを決定します。G(x, y) が G(x-1, y) と G(x+1, y) の間にある場合、線形補間によって対応する重み w を計算します。

w = \frac{ |G(x, y) - G(x-1, y)|}{ |G(x+1, y) - G(x-1, y)|}

最終的に、ピクセル値を保存する条件は次のとおりです。 

G(x, y) >= w * G(x+1, y) + (1 - w) * G(x-1, y) 

 

特定の画像データとグラデーションの方向に応じて、上記のプロセスは他の方向 (45°、90°、135°) にそれぞれ適用されます。

4. 閾値ヒステリシス処理

上記の手順を完了すると、画像内の強いエッジが現在取得されているエッジ画像にすでに含まれています。ただし、一部のゴースト エッジがエッジ イメージ内に存在する場合もあります。これらの仮想エッジは、実際の画像またはノイズによって生成される場合があります。後者の場合は、ノックアウトする必要があります。

このステップでは、二重しきい値処理を使用してエッジの強度を決定します。

  • まず、設定された高しきい値と低しきい値に従って、勾配強度画像のピクセルは、強いエッジ、弱いエッジ、および非エッジの 3 つのカテゴリに分類されます。
  • 強いエッジ ピクセルは、高いしきい値を超える勾配強度を持ちます。
  • 非エッジ ピクセルの勾配強度が低いしきい値を下回っています。
  • 弱いエッジ ピクセルの勾配の強さは 2 つのしきい値の間にあります。

5. エッジ接続

最後のステップでは、強いエッジ ピクセルと隣接する弱いエッジ ピクセルがエッジ接続アルゴリズムによって接続され、完全なエッジが形成されます。一般に、弱いエッジ ピクセルは、少なくとも 1 つの強いエッジ ピクセルに隣接している場合、エッジの一部とみなされます。このプロセスは再帰的または反復的に実装できます。

プログラムフローチャート

画像リンク:  https://pic4.zhimg.com/80/v2-7400b8669ef4c750aeff ​​27ed699ba7c7_720w.webp

Cannyの機能と使い方

OpenCV は、  Canny エッジ検出を実装する関数 cv2.Canny() を提供しており、その構文は次のとおりです。

edges = cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])

 の:

  •  edges は計算されたエッジ イメージです。
  • image は 8 ビット入力イメージです。
  • Threshold1 は、処理中の最初のしきい値を表します。
  • threshold2 は、処理中の 2 番目のしきい値を表します。
  • apertureSize は、Sobel オペレーターの絞りサイズを表します。
  • L2gradientは画像の勾配の大きさを計算するためのロゴです。デフォルト値は False です。True の場合、より正確な L2 ノルム (つまり、両方向の導関数の平方根) を計算に使用します。それ以外の場合は、L1 ノルム (2 方向の導関数の絶対値を直接加算します) を使用します。


例:
関数 cv2.Canny() を使用して画像のエッジを取得し、threshold1 とthreshold2 の異なるサイズを試します。

import cv2
o=cv2.imread("lena.bmp",cv2.IMREAD_GRAYSCALE)
r1=cv2.Canny(o,128,200)
r2=cv2.Canny(o,32,128)
cv2.imshow("original",o)
cv2.imshow("result1",r1)
cv2.imshow("result2",r2)
cv2.waitKey()
cv2.destroyAllWindows()

 

操作結果: 

プログラムの実行結果から、関数 cv2.Canny() のパラメータthreshold1とthreshold2が小さいほど、より多くのエッジ情報を取得できることがわかります。 

おすすめ

転載: blog.csdn.net/weixin_45897172/article/details/131030659