當我們做物件辨識時,透過輪廓可得到特定物件的資訊,協助我們做判斷,OpenCV的findContours()函式可找到影像的輪廓,依實際需求調整參數輸入,而這邊的輪廓和Sobel這些找邊緣的處理不同,Sobel是將物件內部消除,只保留物件邊緣,findContours是在經過Sobel處理之後,將這個只有邊緣的影像,把各個邊緣點做分類,連結的邊緣點儲存在同個容器內,當我們找到輪廓後,可用drawContours()劃出輪廓線,檢查是否取得正確或適合的輪廓。
以下列出兩個多載使用的函式:
OpenCV找輪廓
void findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Pointoffset=Point())
void findContours(InputOutputArray image, OutputArrayOfArrays contours, int mode, int method, Point offset=Point())
- image:輸入圖,使用八位元單通道圖,所有非零的像素都會列入考慮,通常為二極化後的圖。
- contours:包含所有輪廓的容器(vector),每個輪廓都是儲存點的容器(vector),所以contours的資料結構為vector< vector>。
- hierarchy:可有可無的輸出向量,以階層的方式記錄所有輪廓。
- mode:取得輪廓的模式。
- method:儲存輪廓點的方法。
mode:取得輪廓的模式,有以下幾種可選擇:
- CV_RETR_EXTERNAL:只取最外層的輪廓。
- CV_RETR_LIST:取得所有輪廓,不建立階層(hierarchy)。
- CV_RETR_CCOMP:取得所有輪廓,儲存成兩層的階層,首階層為物件外圍,第二階層為內部空心部分的輪廓,如果更內部有其餘物件,包含於首階層。
- CV_RETR_TREE:取得所有輪廓,以全階層的方式儲存。
method:儲存輪廓點的方法,有以下幾種可選擇:
- CV_CHAIN_APPROX_NONE:儲存所有輪廓點。
- CV_CHAIN_APPROX_SIMPLE:對水平、垂直、對角線留下頭尾點,所以假如輪廓為一矩形,只儲存對角的四個頂點。
OpenCV畫輪廓線
void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point())
- image:輸入輸出圖,會將輪廓畫在此影像上。
- contours:包含所有輪廓的容器(vector),也就是findContours()所找到的contours。
- contourIdx:指定畫某個輪廓。
- color:繪製的顏色。
- lineType:繪製的線條型態。
- hierarchy:輪廓階層,也就是findContours()所找到的hierarchy。
- maxLevel:最大階層的輪廓,可以指定想要畫的輪廓,有輸入hierarchy時才會考慮,輸入的值代表繪製的層數。
maxLevel:
- 0:繪製指定階層的輪廓。
- 1:繪製指定階層的輪廓,和他的一階子階層。
- 2:繪製指定階層的輪廓,和他的一階、二階子階層。
- 剩下數字依此類推。
以下程式碼我們先用Canny()標出物體的邊緣,接著呼叫findContours()將邊緣歸類為輪廓,呼叫drawContours()讓我們確認找到哪些輪廓: