Canny edge detectionは画像の輪郭部分を抽出するのに、よく用いられるのですが、詳細なアルゴリズムを理解しないまま使われている事も多いのではないでしょうか?(それ、私)
特に、ヒステリシスしきい値の部分などは、詳細な説明も少ないので、今回、まとめてみたいと思います。
まずは処理結果から。
→ | ||
処理前画像 | Canny edge detection処理後 |
大まかな流れとしては
1.ノイズ除去
ガウシアンフィルタなどでノイズを除去します
2.輪郭抽出
ソーベルフィルタで輪郭を抽出します
3.非極大抑制
エッジの強さが極大となる部分以外を除外します。
詳細は後述
4.ヒステリシスしきい値処理
詳細は後述
完成!!
以上の4ステップで成り立っていますが、非極大抑制とヒステリシスしきい値処理がちょっとわかりづらいので、詳細は以下の通りです。
非極大抑制
ソーベルフィルタ後のエッジの強さを3D表示すると、こんな感じ↓になります。
この山の尾根のみを抽出するのが、非極大抑制となります。
→ |
具体的には、まず、ソーベルフィルタでエッジの強さを求めて、エッジの角度を求めます。
横方向
縦方向
エッジの強さ
エッジの角度(実際にはエッジの線に直行する向きが求まります)
エッジの向き(エッジの法線方向)が求まったら、
0°(-22.5°~22.5°)
45°(22.5°~47.5°)
90°(47.5°~112.5°)
135°(112.5°~157.5°)
の4つに分類します。
エッジの法線方向の3画素のエッジの強さを用いて、中央のエッジの強さが、残す2つの良さよりも大きければ、その部分が極大点ということになり、中央のエッジの強さが最大とならない部分を除外する処理が非極大抑制となります。
→ | ||
エッジの強さ | 非極大抑制 |
この処理によりエッジの部分の細線化が行われます。
ヒステリシスしきい値処理
ヒステリシスしきい値の処理については、Webで探してもあまりわかりやすいのが無いような気がしますが、以下の通りです。
まず、非極大抑制処理で細線化された画像に対して、2つのしきい値を用いて二値化します。
2つのしきい値は、なんとなくエッジっぽい部分(しきい値「小」)と、確実にエッジな部分(しきい値「大」)となるしきい値を設定します。
非極大抑制処理画像
しきい値「小」 | しきい値「大」 |
この2つの画像を用いて、しきい値「小」の中から、しきい値「大」につながっている部分のみを残します。
分かりやすいように、しきい値「小」の画像にしきい値「大」のエッジを赤くして重ね合わせて表示すると↓
この赤い線につながっていない部分を除外します。
この処理がまさにCanny edge detectionとなります。
(参考)
OpenCV 3.0.0-dev documentation Canny Edge Detection
関連記事
←画像処理アルゴリズムへ戻る
コメント
[…] Canny edge detectionの処理アルゴリズム | イメージングソリューション […]
canny法について勉強している者です.書物等で調べてもパッとイメージしにくく
調べているうちにこちらのページに辿り着きました.
ソーベルフィルタ後のエッジの強さを3D表示されているかと思いますが,
どのようなソフトを使って示されていますでしょうか?
m-oshimaさん、コメント頂きありがとうございます。
ここで使用している3D表示ですが、半分、公私混同ではあるのですが、以前、会社で作成したAZP-8100(現在は生産終了)というソフトで表示しています。
https://www.avaldata.co.jp/products/imaging/item/azp-8100
内容的にはOpenGLを使ってライブラリを作成し、そのライブラリをC#でラップして使用しています。
そのため、現在では使用できない状況なのですが、輝度値をCSVファイルに出力する事ができれば、Excelの等高線のグラフ表示で、似た感じの表示ができると思います。
(確か256x256個のデータまでしか表示出来ないと思います)
135°と45°の画像は逆なような気がするのですが、これであっているでしょうか?違っていたらごめんなさい!!
ここでの角度については、エッジの向きに応じて処理を変えるためのフラグ的な使い方をしているので、あまりこだわりが無いのですが、基本的には右手座標系のつもりで角度を定義しているつもりでして、画像の左から右の向きが+X方向、画像の上から下の向きが+Y方向、画像の手間から奥への方向が+Z方向で、回転方向は時計回りを正の方向にしているつもりです。
他の文献等を探すと135°と45°が逆の説明もあるかと思いますが、プログラム上、極大値を探す方向(赤い点の位置)が合っていれば良いんじゃないでしょうかね?
[…] 3/20 Canny edge detection […]