Canny edge detectionの処理アルゴリズムついてはこちらのページ
で紹介していますが、Canny edge detectionで画像のエッジ部分を抽出すると、明確なエッジがなくとも、風景画などの、自然な画像においてもエッジ部分を抽出してくれます。
処理アルゴリズムはやや複雑ですが、OpenCVではCanny()関数を使う事で、簡単にできてしまいます。
Canny()関数の構文
Canny( image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]] ) -> edges
引数
image | 入力画像(8bitグレースケールのみ) |
threshold1 | エッジしきい値(小) |
threshold2 | エッジしきい値(大) |
apertureSize | Sobelフィルタ処理のカーネルのサイズ(3, 5, 7 のいずれか) |
L2gradient | X方向とY方向のSobleフィルタから、エッジの大きさを求める方法 Falseのとき:L1ノルム(X方向の絶対値とY方向の絶対値の和)(初期値) Trueのとき:L2ノルム(X方向の2乗とY方向の2乗の和の平方根) |
戻り値
edges | Canny edge detectionの処理画像 |
サンプルプログラム
Canny edge detection処理のサンプルプログラムを示します。
import cv2
# グレースケールで画像を読み込む
src_img = cv2.imread("image.bmp", cv2.IMREAD_GRAYSCALE)
# Canny edge detection
canny_img = cv2.Canny(src_img, 100, 200)
# 入力画像とCanny edge detectionの処理画像の表示
cv2.imshow("Image", src_img)
cv2.imshow("Canny", canny_img)
cv2.waitKey()
処理結果
Cannyのしきい値の決め方
Cannyで処理するエッジのしきい値(threshold1, threshold2)はしきい値(小)としきい値(大)説明しましたが、これだけだと少々わかりづらいかと思いますが、このしきい値は、L2gradientの設定を初期状態で行うと、X方向のSobelフィルタとY方向のSobelフィルタ処理の結果をそれぞれの絶対値の和の画像に対して、非極大抑制を行った画像に対するヒステリシスしきい値の小さい方のしきい値と大きい方のしきい値になります。
と、説明すると余計に分からないw
しきい値の意味合い的には
threshold1 | エッジの候補としたいエッジ強度のしきい値(エッジが多めに残る) |
threshold2 | 必ずエッジとして残したい部分のエッジ強度のしきい値(エッジが少なめに残る) |
Cannyで処理を行った画像は、threshold2で抽出したエッジと、threshold2のエッジとつながっているthreshold1のエッジを残すようになります。
threshold1、threshold2の値は255を超えた値も有効である事に注意してください。
現実的には、どの程度のしきい値が最適なのか?わかりづらいので、threshold1とthreshold2の値を同じ値で、しきい値(小)の値と、しきい値(大)の値のそれぞれのCanny処理後の画像を確認し、最適な値を見つけると良いかと思います。
処理例のプログラム
/import cv2
# グレースケールで画像を読み込む
src_img = cv2.imread("image.bmp", cv2.IMREAD_GRAYSCALE)
# しきい値(小)の画像
threshold1 = 100
canny_thre1 = cv2.Canny(src_img, threshold1, threshold1)
# しきい値(大)の画像
threshold2 = 500
canny_thre2 = cv2.Canny(src_img, threshold2, threshold2)
# Cannyフィルタの画像
canny_img = cv2.Canny(src_img, threshold1, threshold2)
# 入力画像とCanny edge detectionの処理画像の表示
cv2.imshow("Image", src_img)
cv2.imshow("threshold1", canny_thre1)
cv2.imshow("threshold2", canny_thre2)
cv2.imshow("Canny", canny_img)
cv2.waitKey()
処理結果
thireshold1(しきい値小)のエッジの中から、thireshold2(しきい値大)のエッジに繋がっている部分を残した画像がCanny処理後の画像になります。