エッジ検出アルゴリズム比較 - Sobel, Canny, Laplacian の原理と使い分け
エッジ検出の基本原理 - 画像の微分と勾配の概念
エッジ検出は画像内の輝度が急激に変化する境界を特定する処理で、物体認識、セグメンテーション、特徴抽出の基盤となる最も重要な画像処理技術の一つです。数学的には画像の「微分」に相当し、輝度変化の大きさと方向を計算します。
1 次微分 (勾配) によるエッジ検出: 画像を 2 次元関数 f(x,y) とみなすと、各点での勾配ベクトルは偏微分で定義されます。勾配の大きさ (マグニチュード) が大きい点がエッジです。
|∇f| = √((∂f/∂x)² + (∂f/∂y)²)
勾配の方向 θ = arctan(∂f/∂y / ∂f/∂x) はエッジに垂直な方向を示します。Sobel フィルタや Prewitt フィルタはこの 1 次微分を離散近似するカーネルです。
2 次微分 (ラプラシアン) によるエッジ検出: 2 次微分のゼロ交差点 (正から負、または負から正に変わる点) がエッジに対応します。ラプラシアンは方向に依存しない等方的な演算子です。
∇²f = ∂²f/∂x² + ∂²f/∂y²
エッジの種類: ステップエッジ (急激な変化)、ランプエッジ (緩やかな変化)、ルーフエッジ (線状の構造) など、実画像には様々なエッジパターンが存在します。アルゴリズムによって検出しやすいエッジの種類が異なるため、用途に応じた選択が重要です。実際のアプリケーションでは、自動運転の車線検出、製造業の欠陥検査、医療画像の臓器境界抽出など、エッジ検出が中核技術として機能しています。
Sobel フィルタ - 方向性を持つ 1 次微分エッジ検出
Sobel フィルタは最も広く使用されている 1 次微分ベースのエッジ検出手法です。水平方向と垂直方向の勾配を個別に計算し、それらを合成してエッジの強度と方向を求めます。ノイズに対する耐性と計算効率のバランスに優れています。
Sobel カーネル:
水平方向 (Gx): [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
垂直方向 (Gy): [[-1, -2, -1], [0, 0, 0], [1, 2, 1]]
中央行/列に 2 倍の重みを持たせることで、ガウシアン平滑化の効果を含み、単純な差分フィルタ (Prewitt) よりノイズ耐性が高くなっています。
OpenCV での実装:
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
magnitude = np.sqrt(sobelx**2 + sobely**2)
direction = np.arctan2(sobely, sobelx)
cv2.CV_64F を指定して 64bit 浮動小数点で計算することで、負の勾配値も正確に保持します。8bit で計算すると負の値がクリップされ、片方向のエッジしか検出できません。
ksize パラメータ: カーネルサイズを 3, 5, 7 から選択できます。大きいカーネルはノイズ耐性が高まりますが、エッジの位置精度が低下します。ksize=3 が最も一般的で、ノイズが多い画像では事前にガウシアンぼかしを適用してから ksize=3 で処理する方が、大きなカーネルを使うより良い結果が得られます。
Sobel の利点と限界: 計算が高速で実装が容易、方向情報が得られる点が利点です。一方、エッジの太さが一定でない (太いエッジが生成される)、閾値の設定が必要、ノイズに完全には強くない点が限界です。
Canny エッジ検出 - 最適エッジ検出の理論と実装
Canny エッジ検出は 1986 年に John Canny が提案した、理論的に最適なエッジ検出アルゴリズムです。「良い検出」「良い位置精度」「単一応答」の 3 つの基準を最適化するよう設計されており、最も広く使用されるエッジ検出手法です。
Canny の 4 段階処理:
1. ガウシアン平滑化: ノイズを除去するためにガウシアンフィルタを適用します。σ (標準偏差) が大きいほどノイズ耐性が高まりますが、細いエッジが失われます。一般的に σ=1.0-2.0 が使用されます。
2. 勾配計算: Sobel フィルタで水平・垂直方向の勾配を計算し、マグニチュードと方向を求めます。
3. 非極大値抑制 (Non-Maximum Suppression): 勾配方向に沿って、各ピクセルが局所的な最大値であるかを判定します。最大値でないピクセルを抑制 (ゼロに) することで、エッジを 1 ピクセル幅の細い線に絞り込みます。これが Canny の最大の特徴で、Sobel では得られない鮮明なエッジラインを生成します。
4. ヒステリシス閾値処理: 2 つの閾値 (高閾値 T_high、低閾値 T_low) を使用します。マグニチュードが T_high 以上のピクセルは確実なエッジ、T_low 以下は非エッジ、その間のピクセルは確実なエッジに接続している場合のみエッジとして採用します。これにより、弱いエッジの途切れを防ぎつつノイズを排除します。
OpenCV での実装:
edges = cv2.Canny(gray, threshold1=50, threshold2=150)
threshold1 が T_low、threshold2 が T_high に対応します。一般的に T_high:T_low = 2:1 〜 3:1 の比率が推奨されます。
Laplacian フィルタ - 2 次微分による等方的エッジ検出
Laplacian (ラプラシアン) フィルタは 2 次微分に基づくエッジ検出手法で、方向に依存しない等方的な検出が特徴です。1 次微分の Sobel が勾配の「大きさ」を検出するのに対し、Laplacian は勾配の「変化率」を検出します。
Laplacian カーネル:
基本形: [[0, 1, 0], [1, -4, 1], [0, 1, 0]]
対角含む: [[1, 1, 1], [1, -8, 1], [1, 1, 1]]
中心値の絶対値が周囲の値の合計に等しく、均一領域での出力がゼロになるよう設計されています。
ゼロ交差によるエッジ検出: Laplacian の出力は正と負の値を持ち、エッジはゼロ交差点 (正から負、または負から正に変わる点) として検出されます。ゼロ交差点はサブピクセル精度でのエッジ位置特定が可能で、Sobel より位置精度が高い場合があります。
LoG (Laplacian of Gaussian): Laplacian はノイズに非常に敏感なため、実用上はガウシアン平滑化と組み合わせた LoG フィルタとして使用します。ガウシアンの σ がスケールパラメータとなり、検出するエッジのスケール (太さ) を制御します。
log = cv2.GaussianBlur(gray, (0, 0), sigma)
log = cv2.Laplacian(log, cv2.CV_64F)
DoG (Difference of Gaussians) による近似: LoG は計算コストが高いため、異なる σ のガウシアンぼかしの差分 (DoG) で近似されることがあります。SIFT 特徴量検出ではこの DoG が使用されています。
Laplacian の利点と限界: 方向に依存しない等方的検出、ゼロ交差による高精度な位置特定が利点です。一方、ノイズに極めて敏感、エッジの方向情報が得られない、二重エッジ (正と負の両側) が生成される点が限界です。
3 手法の性能比較 - 用途別の最適選択ガイド
Sobel、Canny、Laplacian の 3 手法を複数の評価軸で比較し、用途に応じた最適な選択指針を提供します。実際の画像処理パイプラインでは、これらを組み合わせて使用することも一般的です。
比較表:
- ノイズ耐性: Canny > Sobel > Laplacian。Canny はガウシアン平滑化とヒステリシス閾値で高いノイズ耐性を実現。Laplacian は 2 次微分のためノイズを強く増幅します。
- エッジの細さ: Canny > Laplacian > Sobel。Canny の非極大値抑制により 1px 幅のエッジが得られます。Sobel は太いエッジを生成しがちです。
- 位置精度: Canny ≈ Laplacian > Sobel。非極大値抑制とゼロ交差はサブピクセル精度を実現します。
- 計算速度: Sobel > Laplacian > Canny。Sobel は単純なカーネル畳み込みのみ。Canny は 4 段階の処理が必要です。
- 方向情報: Sobel (あり) > Canny (あり) > Laplacian (なし)。Sobel と Canny は勾配方向を出力できます。
- パラメータ調整: Sobel (少) < Laplacian (少) < Canny (多)。Canny は 2 つの閾値とσの調整が必要です。
用途別推奨:
- リアルタイム処理 (動画、ロボットビジョン): Sobel。計算速度が最優先の場面で選択します。
- 汎用的なエッジ検出 (物体認識、セグメンテーション): Canny。品質と汎用性のバランスが最も優れています。
- ブロブ検出、スケール空間解析: LoG/Laplacian。SIFT や SURF などの特徴量検出の基盤として使用されます。
- 産業用検査 (欠陥検出): Canny + モルフォロジー演算の組み合わせ。高精度なエッジ検出後に形状解析を行います。
実装とパイプライン構築 - エッジ検出の前処理と後処理
エッジ検出を実際のアプリケーションに組み込む際は、前処理と後処理が結果の品質を大きく左右します。ノイズ除去、閾値の自動決定、エッジの後処理を含む完全なパイプラインを構築します。
前処理: ノイズ除去: エッジ検出前のノイズ除去は必須です。ガウシアンぼかし (cv2.GaussianBlur) が最も一般的ですが、エッジを保持したい場合はバイラテラルフィルタ (cv2.bilateralFilter) が有効です。メディアンフィルタはごま塩ノイズに特に効果的です。
Canny の閾値自動決定: Otsu の方法で画像の最適閾値を求め、それを基に Canny の閾値を設定する手法が広く使用されています。
otsu_thresh, _ = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)
edges = cv2.Canny(gray, otsu_thresh * 0.5, otsu_thresh)
この方法により、画像の特性に応じた適応的な閾値設定が可能になります。
後処理: エッジの接続と整形: Canny の出力は途切れたエッジを含む場合があります。膨張 (cv2.dilate) で近接するエッジを接続し、細線化 (Thinning) で 1px 幅に戻す手順が有効です。輪郭検出 (cv2.findContours) で閉じた輪郭を抽出し、面積フィルタリングで小さなノイズ輪郭を除去します。
マルチスケールエッジ検出: 単一スケールでは検出できないエッジを捉えるため、異なるσのガウシアンぼかしを適用してから Canny を実行し、結果を統合します。細いエッジ (小さいσ) と太いエッジ (大きいσ) の両方を検出できます。
深層学習ベースのエッジ検出: HED (Holistically-Nested Edge Detection) や BDCN などの CNN ベースの手法は、従来手法を大幅に上回る品質のエッジ検出を実現しています。意味的なエッジ (物体の境界) とテクスチャエッジを区別でき、人間の知覚に近い結果を生成します。ただし計算コストが高く、GPU が必要です。