要畫輪廓要先有邊緣檢測
邊緣檢測Edge detection是影像處理,幫助電腦可以抓取圖片中的物體,這項技術以檢查影像中各像素點的顏色變化來區分邊界,有邊緣之後,可以再從這些交錯的線條得到物體輪廓。
邊緣檢測 vs. 輪廓檢測
在圖像中有個容易搞混的概念,邊緣與輪廓的差異是什麼?
邊緣檢測:檢測圖像中像素的值有突然改變的地方。
輪廓檢測:檢測圖像中的物體邊界,也就像找出物體的邊界。
因此要知道有邊緣的地方不一定有邊界,有邊界的地方也不一定有邊緣。
邊緣檢測Edge detection
Python的opencv提供三種邊緣檢測的方法:Laplacian、Sobel、Canny,這三個技術都是利用灰階圖片,基於每個像素灰值的不同,利用不同物體在其邊界處會有明顯的邊緣特徵來檢測。
這三種方法可依技術原理分為兩種,以下為其餘補充事項。
Laplacian:對於圖片的雜訊相當敏感,因此通常會先將影像模糊化再做處理。
Sobel與Canny:這兩個方法擁有相同的底層技術,差異在於執行方式,Sobel以簡單的卷積過濾器偵測圖像上水平及縱向光度的改變,以加權平均方式計算各點的數值來決定邊緣。而Canny先將影像模糊化再進行非極大值抑制,因為Canny有先經過影像模糊化,故比較能處理影像雜訊問題。
編寫程式碼該注意事項
使用opencv中的Laplacian函式須指定輸出的影像浮點格式CV_64F,為什麼是使用64bits而非灰階的8bits呢?
因為Laplacian過程需進行black-to-white及white-to-black兩種轉換,在微分的梯度計算中black-to-white屬於正向的運算而white-to-black則是負向,灰階的8bits格式僅能儲存0-255的正值,因此必須使用64bits。
接下來須取其絕對值並轉為8bit的灰階資訊,這是一般在運行Laplacian運算時所建議的方法,網上的說法是此方式可保留所有的邊緣資訊:先轉出為64bit,再取絕對值轉為8bit。
Sobel可以單獨針對X軸、Y軸、X與Y軸抓取其邊緣。
Canny 的邊緣檢測方法是先將影響模糊化去除不必要的資訊,再使用類似Sobel的方式取的XY軸邊緣。
Canny函式的第二與第三個參數是門檻參數,意指圖像的任一點像素,若其值大於threshold2,則認定它屬於邊緣像素,若小於threshold1則不為邊緣像素,介於兩者之間則由程式依其像素強度值運算後決定。
程式碼與實作效果
程式碼連結:https://gist.github.com/IvyQQQQQ/30e57cc081da76399c267d344a7b8dbb
輪廓檢測
使用上面的方法找出邊緣後,接下來便是確定輪廓。輪廓是一連串沒有間斷的點所組成的曲線。我們可借助opencv中的 cv2.findContours找到輪廓,利用cv2.boundingRect依照前面跑出的結果取出物體。圖像處理步驟如下:
程式碼與實作效果
程式碼連結:https://gist.github.com/IvyQQQQQ/e3dc2d7f69211fd5790fcf78bbd93905
參考連結
https://chtseng.wordpress.com/2016/12/05/opencv-edge-detection%E9%82%8A%E7%B7%A3%E5%81%B5%E6%B8%AC/