【小林的OpenCV基礎課 10】Canny邊緣檢測
新しい年が近づいてくる,みなさんに新年をお祈りします。
預祝同學們新年大吉(吧(づ ̄ 3 ̄)づ)
嗯,邊緣檢測,聽起來挺高大上的,感覺終於從之前的濾波和模糊中解脫出來了。
邊緣檢測,顧名思義,就是找出圖像中的各種邊緣(通常邊緣都是以曲線的形式呈現的),然後標出來。可是機器怎麼知道哪裡是邊緣呢?這就涉及到邊緣檢測的原理了。
這一話依舊分為三部分:
- Canny邊緣檢測原理
- 對應的函數講解
- Demo時間
Canny邊緣檢測原理
同學們可以先閱讀【小林的OpenCV基礎課 番外】極簡邊緣運算元基礎知識來充充電。
Canny邊緣檢測的思想:
- 通過求導和求梯度確定所有的長得像「邊緣」的像素
- 去掉最不像「邊緣」的像素
- 區分強邊緣(保留)和弱邊緣(待定)
使用Canny邊緣檢測時對圖像的預處理:
- 使用高斯濾波器濾除雜訊(導數對雜訊肥腸敏感)
具體的實現步驟(即Canny演算法是如何找出邊緣的):
- 使用邊緣運算元求出x和y方向的一階導數值 和
- 計算梯度值 和方向角
- 非極大值抑制,將局部最大值之外的所有梯度值抑製為0,消除雜散效應
- 雙閾值篩選強弱邊緣,a.如果邊緣像素的梯度值>高閾值,則將其標記為強邊緣像素;b.如果低閾值<邊緣像素的梯度值<高閾值,則將其標記為弱邊緣像素;c.如果邊緣像素的梯度值<低閾值,則會被抑制
- 確定弱邊緣像素的去留,若其鄰域內有強鄰域像素,則該弱邊緣像素會變成強邊緣像素
Canny函數講解
edges=cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]])
- edges:輸出的邊緣圖,需要和源圖片有一樣的尺寸和類型
- image:待處理的圖像
- thresh1和thresh2:分別為低閾值和高閾值,建議高低閾值之比為3:1到2:1之間
- aptertureSize:應用Sobel運算元的孔徑大小,有默認值3
- L2gradient:計算圖像梯度幅值的標識,有默認值false
Demo時間
有同學小的時候喜歡把手按在紙上,用筆描出手的輪廓。小林這裡有一隻手的照片,我們要做出這隻手的邊緣圖像:
import cv2import numpy as npimg = cv2.imread(hand1.jpg)# 首先進行高斯濾波 濾除干擾blurImg = cv2.GaussianBlur(img, (9, 9), 0)cannyImg = cv2.Canny(blurImg, 50, 130)cv2.namedWindow(Canny)cv2.namedWindow(Blur)cv2.imshow(Canny, cannyImg)cv2.imshow(Blur, blurImg)cv2.waitKey()cv2.destroyAllWindows()
嗯 作業!
1.請同學們使用一種簡單的方法將得到的邊緣圖像疊加到原圖上。提示:
- 邏輯運算
- 掩膜操作
- 邊緣圖的像素值,可以在控制台中列印出像素值
- BGR空間是如何呈現顏色的
2.同學們會想,如果對閾值化後的圖像進行邊緣檢測會不會效果好一點?
- 試一試不就知道啦
這一話講解部分的Demo代碼和作業的Demo代碼已經同步至Github,分別對應Class 4 Image Processing文件夾下的C4 Canny.py和C4 HW Canny.py兩個文件。
最後的最後
如果喜歡小林的專欄,就收藏了吧!してください!
推薦閱讀: