一.高斯濾波
????????因為圖像邊緣檢測就是把像素值有差異的地方提取出來,所以噪聲會有很大影響,因此需要對圖像進行平滑處理,高斯濾波是流程中常用的方法。
二.計算圖像的梯度與方向
過程中通常使用sobel算子進行梯度計算,在OpenCV中,默認使用?G=|G(x)+G(y)|?來計算梯度值。
這個角度值其實是當前邊緣的梯度方向,若梯度方向不是0°、45°、90°、135°這種特定角度,那么就要用到插值算法來計算當前像素點在其方向上進行插值的結果,然后進行比較并判斷是否保留該像素點。
- 為-22.5°~22.5°,或-157.5°~157.5°,則認為邊緣為水平邊緣;
- 為22.5°~67.5°,或-112.5°~-157.5°,則認為邊緣為45°邊緣;
- 為67.5°~112.5°,或-67.5°~-112.5°,則認為邊緣為垂直邊緣;
- 為112.5°~157.5°,或-22.5°~-67.5°,則認為邊緣為135°邊緣;
三.非極大值抑制
????????經過第二步得到的邊緣不經過處理是沒辦法使用的,因為高斯濾波去噪后邊緣會模糊,得到的邊緣像素點非常多,因此需要對其進行一些過濾操作,而非極大值抑制就是一個很好的方法。即檢查每個像素點的梯度方向上的相鄰像素,并保留梯度值最大的像素,將其他像素抑制為零。
四.雙閾值篩選
經過非極大值抑制之后,我們還需要設置閾值來進行篩選。
????????當某一像素位置的幅值超過最高閾值時,該像素必是邊緣像素;當幅值低于最低閾值時,該像素必不是邊緣像素;幅值處于最高像素與最低像素之間時,如果它能連接到一個高于閾值的邊緣時,則被認為是邊緣像素,否則就不會被認為是邊緣。
五.實現邊緣檢測的流程函數
edges = cv2.Canny(image, threshold1, threshold2)
- threshold1:低閾值,用于決定可能的邊緣點。
- threshold2:高閾值,用于決定強邊緣點。
- 即使讀到的是彩色圖也可以進行處理。
import cv2 as cvimg = cv.imread('../images/lvbo2.png')gray1 = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 手動進行高斯濾波再調用canny邊緣檢測
img2 = cv.GaussianBlur(img, (3, 3), 1)gray2 = cv.cvtColor(img2, cv.COLOR_BGR2GRAY)# 二值化處理方便觀察
ret, binary = cv.threshold(gray1, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
ret, binary1 = cv.threshold(gray2, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)# 利用內置高斯濾波器進行邊緣檢測
edge = cv.Canny(binary, 30, 70)
edge1 = cv.Canny(binary1, 30, 70)cv.imshow('edge', edge)
cv.imshow('edge1', edge1)
cv.waitKey(0)
cv.destroyAllWindows()
????????可以發現,提前手動進行去噪處理效果更好,雖然canny函數內置了高斯濾波,但根據要求進行去噪預處理可以得到更好的效果。