Canny edge detection

Canny edge detectionは画像の輪郭部分を抽出するのに、よく用いられるのですが、詳細なアルゴリズムを理解しないまま使われている事も多いのではないでしょうか?(それ、私)

特に、ヒステリシスしきい値の部分などは、詳細な説明も少ないので、今回、まとめてみたいと思います。

まずは処理結果から。

Canny edge detector Canny edge detector
処理前画像 Canny edge detection処理後

大まかな流れとしては

1.ノイズ除去

ガウシアンフィルタなどでノイズを除去します

Canny edge detector

2.輪郭抽出

ソーベルフィルタで輪郭を抽出します

Canny edge detector

3.非極大抑制

エッジの強さが極大となる部分以外を除外します。

詳細は後述

Canny edge detector

4.ヒステリシスしきい値処理

詳細は後述

Canny edge detector

完成!!

以上の4ステップで成り立っていますが、非極大抑制とヒステリシスしきい値処理がちょっとわかりづらいので、詳細は以下の通りです。

非極大抑制

ソーベルフィルタ後のエッジの強さを3D表示すると、こんな感じ↓になります。

Canny edge detector

この山の尾根のみを抽出するのが、非極大抑制となります。

Canny edge detector Canny edge detector

具体的には、まず、ソーベルフィルタでエッジの強さを求めて、エッジの角度を求めます。

横方向

Canny edge detector

縦方向

Canny edge detector

エッジの強さ

Canny edge detector

エッジの角度(実際にはエッジの線に直行する向きが求まります)

Canny edge detector

エッジの向き(エッジの法線方向)が求まったら、

0°(-22.5°~22.5°)

Canny edge detector

45°(22.5°~47.5°)

Canny edge detector

90°(47.5°~112.5°)

Canny edge detector

135°(112.5°~157.5°)

Canny edge detector

の4つに分類します。

エッジの法線方向の3画素のエッジの強さを用いて、中央のエッジの強さが、残す2つの良さよりも大きければ、その部分が極大点ということになり、中央のエッジの強さが最大とならない部分を除外する処理が非極大抑制となります。

Canny edge detector Canny edge detector
エッジの強さ 非極大抑制

この処理によりエッジの部分の細線化が行われます。

ヒステリシスしきい値処理

ヒステリシスしきい値の処理については、Webで探してもあまりわかりやすいのが無いような気がしますが、以下の通りです。

まず、非極大抑制処理で細線化された画像に対して、2つのしきい値を用いて二値化します。

2つのしきい値は、なんとなくエッジっぽい部分(しきい値「小」)と、確実にエッジな部分(しきい値「大」)となるしきい値を設定します。

非極大抑制処理画像

Canny edge detector

Canny edge detector Canny edge detector
しきい値「小」 しきい値「大」

この2つの画像を用いて、しきい値「小」の中から、しきい値「大」につながっている部分のみを残します。

分かりやすいように、しきい値「小」の画像にしきい値「大」のエッジを赤くして重ね合わせて表示すると↓

Canny edge detector

この赤い線につながっていない部分を除外します。

Canny edge detector

この処理がまさにCanny edge detectionとなります。

(参考)

OpenCV 3.0.0-dev documentation Canny Edge Detection

画像処理アルゴリズムへ戻る

コメント

  1. ぽぽっち より:

    135°と45°の画像は逆なような気がするのですが、これであっているでしょうか?違っていたらごめんなさい!!

    • akira より:

      ここでの角度については、エッジの向きに応じて処理を変えるためのフラグ的な使い方をしているので、あまりこだわりが無いのですが、基本的には右手座標系のつもりで角度を定義しているつもりでして、画像の左から右の向きが+X方向、画像の上から下の向きが+Y方向、画像の手間から奥への方向が+Z方向で、回転方向は時計回りを正の方向にしているつもりです。
      他の文献等を探すと135°と45°が逆の説明もあるかと思いますが、プログラム上、極大値を探す方向(赤い点の位置)が合っていれば良いんじゃないでしょうかね?