[OpenCV筆記] 8. Canny邊緣偵測
1.Canny邊緣偵測
1.1. 簡介
Canny邊緣檢測是一種使用多級邊緣檢測演算法偵測邊緣的方法。實作步驟如下:
- 去除雜訊:因為雜訊會影響檢測的準確度,因此使用高斯濾波去除雜訊。
- 計算梯度的幅度與方向。
- 非極大值之抑制:最相關的像素留下,其他歸零。
- 確定邊緣:利用雙設定值演算法進行。
1.2. 實作重點摘要
Canny演算法使用高斯濾波去除雜訊。濾波器越大,邊緣資訊對雜訊的敏感度越低,定位錯誤也會增加。
而非極大值之抑制,簡言之就是在計算過程中將與邊緣最相關的像素留下,其他像素值歸零。如下圖所示,A所在的地方離邊緣最近,計算出的相關數值也會最大,因此A會被保留,而B、C兩點都會被歸零。
source:OpenCV-Python Tutorials:Canny Edge Detection最後,會透過設定maxVal和minVal兩個值來確定邊緣。可能情況有3種:
- 若邊緣像素值 >= maxVal,則標記為強邊緣。
- 若 minVal < 邊緣像素值 < maxVal,則標記為虛邊緣。接著判斷是否與強邊緣連接,若有則視為邊緣,若無,則將其抑制。
- 若邊緣像素值 <= minVal,則抑制目前邊緣像素(歸零)。
如下圖所示,B和C都是虛邊緣,C有與強邊緣A相連結,所以會被保留。而B未與A相連結,則會被捨棄。
source:OpenCV-Python Tutorials:Canny Edge Detection1.3. 程式相關種點說明
img_edge = cv2.Canny(img, minVal, maxVal, apertureSize, L2gradient)
- img_edge為輸出影像。img為輸入影像。
- minVal, maxVal為設定值。
- apertureSize為Sobel大小,通常使用預設即可。
- L2gradient為計算梯度的範數,若設為True,則使用L2範數計算兩個方向導數的平方和再取平方根。預設為False,使用L1範數計算兩個方向導數之絕對值相加。
1.4. 輸出結果分析
1.4.1. 設定值 (minVal, maxVal)
當設定值的值越小,輸出結果的細節會越多。在本例中,我們以 (32, 128) 和 (128, 200) 來比較。"img_canny_L1_low"參數為(32, 128) ,"img_canny_L1"參數為(128, 200),從下圖來看,"img_canny_L1_low" 所保留的細節明顯高於 "img_canny_L1"。
<source:Greatway9999>1.4.2. 範數 (L1、L2)
L2範數計算兩個方向導數的平方和再取平方根。L1範數計算兩個方向導數之絕對值相加。
使用L2範數計算,結果會更精確,因此,和L1範數計算結果相比,L2範數計算結果的細節相較少。右圖為L2輸出結果,其細節確實比中間圖片 (L1輸出結果) 少,特別是帽穗的部分。
<source:Greatway9999>1.5. 完整程式
# Canny邊緣檢測
# 使用高斯濾波去除雜訊。濾波器越大,邊緣資訊對雜訊的敏感度越低,定位錯誤也會增加。
# 設定maxVal和minVal兩個值來確定邊緣。
# 若邊緣像素值 >= maxVal,則標記為強邊緣。
# 若 minVal < 邊緣像素值 < maxVal,則標記為虛邊緣。接著判斷是否與強邊緣連接,若有則視為邊緣,若無,則將其抑制。
# 若邊緣像素值 <= minVal,則抑制目前邊緣像素(歸零)。
import numpy as np
import cv2
img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)
#img_edge = cv2.Canny(img, minVal, maxVal, apertureSize, L2gradient)
# img_edge為輸出影像。img為輸入影像。
# minVal, maxVal為設定值。
# apertureSize為Sobel大小。
# L2gradient為計算梯度的範數,若設為True,則使用L2範數計算兩個方向導數的平方和再取平方根。預設為False,使用L1範數計算兩個方向導數之絕對值相加。
img_canny_L1 = cv2.Canny(img, 128, 200)
img_canny_L2 = cv2.Canny(img, 128, 200, L2gradient = True)
img_canny_L1_low = cv2.Canny(img, 32, 128)
cv2.imshow('img', img)
cv2.imshow('img_canny_L1',img_canny_L1)
cv2.imshow('img_canny_L2',img_canny_L2)
cv2.imshow('img_canny_L1_low',img_canny_L1_low)
cv2.waitKey()
cv2.destroyAllWindows()
#Canny邊緣偵測
---
參考資料:
0 留言