OpenCV 画像エッジ検出
画像エッジ検出はコンピュータビジョンおよび画像処理における基本的なタスクであり、画像内の輝度変化が顕著な領域を特定するために使用されます。これらの領域は通常、物体の境界に対応します。
OpenCV でよく使われるエッジ検出関数とその説明は次のとおりです。
| 関数 | アルゴリズム | 説明 | 適用シーン |
|---|---|---|---|
cv2.Canny() | Canny エッジ検出 | 多段階アルゴリズムで、検出効果が高く、ノイズ抑制能力が強い。 | 汎用エッジ検出に適しており、ほとんどのシーンに適しています。 |
cv2.Sobel() | Sobel オペレータ | 一次導関数に基づくエッジ検出で、水平および垂直エッジを検出できます。 | 水平および垂直エッジの検出。 |
cv2.Scharr() | Scharr オペレータ | Sobel オペレータの改良版で、エッジへの応答がより強い。 | 微細なエッジの検出。 |
cv2.Laplacian() | Laplacian オペレータ | 二次導関数に基づくエッジ検出で、ノイズに敏感。 | エッジとコーナーの検出。 |
1. Canny エッジ検出 (cv2.Canny())
Canny エッジ検出は、1986 年に John F. Canny によって提案された多段階のエッジ検出アルゴリズムです。
Canny エッジ検出は、ノイズ抑制とエッジ位置特定の間で優れたバランスを取ることができるため、エッジ検出の「ゴールドスタンダード」と見なされています。
1.1 Canny エッジ検出の手順
Canny エッジ検出アルゴリズムは、主に以下の手順を含みます。
- ノイズ抑制: ガウシアンフィルタを使用して画像を平滑化し、ノイズの影響を低減します。
- 勾配の計算: Sobel オペレータを使用して画像の勾配の大きさと方向を計算します。
- 非極大値抑制: 勾配方向に沿って、局所的に勾配が最大の画素を残し、他の画素を抑制します。
- 二重閾値検出: 2つの閾値(低閾値と高閾値)を使用して真のエッジを決定します。高閾値より高い画素は強エッジと見なされ、低閾値より低い画素は抑制され、その間の画素は強エッジに接続されている場合に保持されます。
- エッジ接続: ヒステリシス閾値処理により、弱エッジを強エッジに接続し、完全なエッジを形成します。
1.2 OpenCV を使用した Canny エッジ検出の実装
OpenCV では、cv2.Canny()関数を使用して Canny エッジ検出を実装できます。
この関数のプロトタイプは次のとおりです。
edges = cv2.Canny(image, threshold1, threshold2, apertureSize=3, L2gradient=False)
image: 入力画像。単チャンネルのグレースケール画像である必要があります。threshold1: 低閾値。threshold2: 高閾値。apertureSize: Sobel オペレータのアパーチャサイズ。デフォルトは 3 です。L2gradient: L2 ノルムを使用して勾配の大きさを計算するかどうか。デフォルトは False(L1 ノルムを使用)です。
例
import numpy as np
# 画像を読み込む
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
# Canny エッジ検出を適用
edges = cv2.Canny(image, 100, 200)
# 結果を表示
cv2.imshow('Canny Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
2. Sobel オペレータ (cv2.Sobel())
Sobel オペレータは勾配ベースのエッジ検出オペレータであり、画像の水平および垂直方向の勾配を計算することでエッジを検出します。
Sobel オペレータはガウス平滑化と微分操作を組み合わせているため、ノイズに対して一定の抑制効果があります。
2.1 Sobel オペレータの原理
Sobel オペレータは、2つの 3x3 の畳み込みカーネルを使用して、画像の水平および垂直方向の勾配をそれぞれ計算します。
- 水平方向の畳み込みカーネル:
[-1, 0, 1] [-2, 0, 2] [-1, 0, 1]
- 垂直方向の畳み込みカーネル:
[-1, -2, -1] [ 0, 0, 0] [ 1, 2, 1]
この2つの畳み込みカーネルにより、画像の水平および垂直方向の勾配をそれぞれ取得できます。GxとGy最終的な勾配の大きさは、以下の式で計算できます。
G = sqrt(Gx^2 + Gy^2)
2.2 OpenCV を使用した Sobel オペレータの実装
OpenCV では、cv2.Sobel()関数を使用して画像の勾配を計算できます。この関数のプロトタイプは次のとおりです。
dst = cv2.Sobel(src, ddepth, dx, dy, ksize=3, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
src: 入力画像。ddepth: 出力画像の深度。通常は使用します。cv2.CV_64F。dx: x 方向の微分次数。dy: y 方向の微分次数。ksize: Sobel カーネルのサイズ。デフォルトは 3 です。scale: スケール係数。デフォルトは 1 です。delta: オプションのデルタ値。デフォルトは 0 です。borderType: 境界パディングタイプ。デフォルトはcv2.BORDER_DEFAULT。
例
import numpy as np
# 画像を読み込む
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
# x 方向の勾配を計算
sobel_x = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3)
# y 方向の勾配を計算
sobel_y = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3)
# 勾配の大きさを計算
sobel_combined = np.sqrt(sobel_x**2 + sobel_y**2)
# 結果を表示
cv2.imshow('Sobel X', sobel_x)
cv2.imshow('Sobel Y', sobel_y)
cv2.imshow('Sobel Combined', sobel_combined)
cv2.waitKey(0)
cv2.destroyAllWindows()
3. Laplacian オペレータ (cv2.Laplacian())
Laplacian オペレータは二次微分オペレータであり、画像の二次導関数を計算することでエッジを検出します。Laplacian オペレータはノイズに比較的敏感であるため、通常は使用前に画像にガウス平滑化を適用します。
3.1 Laplacian オペレータの原理
Laplacian オペレータは、以下の畳み込みカーネルを使用して画像の二次導関数を計算します。
[ 0, 1, 0] [ 1, -4, 1] [ 0, 1, 0]
この畳み込みカーネルにより、画像の Laplacian 値を取得できます。Laplacian 値が大きい領域は通常、画像のエッジに対応します。
3.2 OpenCV を使用した Laplacian オペレータの実装
OpenCV では、cv2.Laplacian()関数を使用して画像の Laplacian 値を計算できます。
この関数のプロトタイプは次のとおりです。
dst = cv2.Laplacian(src, ddepth, ksize=1, scale=1, delta=0, borderType=cv2.BORDER_DEFAULT)
src: 入力画像。ddepth: 出力画像の深度。通常は使用します。cv2.CV_64F。ksize: Laplacian カーネルのサイズ。デフォルトは 1 です。scale: スケール係数。デフォルトは 1 です。delta: オプションのデルタ値。デフォルトは 0 です。borderType: 境界パディングタイプ。デフォルトはcv2.BORDER_DEFAULT。
例
import numpy as np
# 画像を読み込む
image = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
# Laplacian オペレータを適用
laplacian = cv2.Laplacian(image, cv2.CV_64F)
# 結果を表示
cv2.imshow('Laplacian', laplacian)
cv2.waitKey(0)
cv2.destroyAllWindows()
よく使われるエッジ検出関数の比較
以下は、OpenCV でよく使われるエッジ検出関数の比較です。
| 関数 | アルゴリズム | 長所 | 短所 | 適用シーン |
|---|---|---|---|---|
cv2.Canny() | Canny エッジ検出 | ノイズ抑制能力が強く、エッジ検出効果が高い。 | パラメータ調整が比較的複雑です。 | 汎用エッジ検出に適しており、ほとんどのシーンに適しています。 |
cv2.Sobel() | Sobel オペレータ | 計算が簡単で、水平および垂直エッジの検出に適しています。 | ノイズに敏感で、エッジ検出効果は普通です。 | 水平および垂直エッジの検出。 |
cv2.Scharr() | Scharr オペレータ | エッジへの応答がより強く、微細なエッジの検出に適しています。 | ノイズに敏感。 | 微細なエッジの検出。 |
cv2.Laplacian() | Laplacian オペレータ | エッジとコーナーを検出できます。 | ノイズに非常に敏感です。 | エッジとコーナーの検出。 |