OpenCV-Python系列之輪廓入門
本次我們將討論OpenCV中的輪廓,輪廓屬於OpenCV中的一個很重要的部分,同時我們在之前講過的Canny邊緣檢測將作為基礎。
輪廓檢測
函式原型:
cv2.findContours(image, mode, method, contours=None, hierarchy=None, offset=None)
引數含義:
image 代表輸入的圖片。注意輸入的圖片必須為二值圖片。若輸入的圖片為彩色圖片,必須先進行灰度化和二值化。
mode 表示輪廓的檢索模式,有4種:
cv2.RETR_EXTERNAL 表示只檢測外輪廓。
cv2.RETR_LIST 檢測的輪廓不建立等級關係。
cv2.RETR_CCOMP 建立兩個等級的輪廓,上面的一層為外邊界,裡面的一層為內孔的邊界資訊。如果內孔內還有一個連通物體,這個物體的邊界也在頂層。
cv2.RETR_TREE 建立一個等級樹結構的輪廓。
method 為輪廓的近似辦法,有4種:
cv2.CHAIN_APPROX_NONE 儲存所有的輪廓點,相鄰的兩個點的畫素位置差不超過1,即max(abs(x1-x2), abs(y2-y1))<=1。
cv2.CHAIN_APPROX_SIMPLE 壓縮水平方向,垂直方向,對角線方向的元素,只保留該方向的終點座標,例如一個矩形輪廓只需4個點來儲存輪廓資訊。
cv2.CHAIN_APPROX_TC89_L1 和 cv2.CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似演算法。
返回值:
cv2.findContours()函式返回兩個值,一個是輪廓本身contours,還有一個是每條輪廓對應的屬性hierarchy。
通常情況下,我們選擇引數cv2.CHAIN_APPROX_SIMPLE,因為我們只需要最簡單的輪廓點的資訊。
輪廓繪製
現在我們來看另一個函式:
cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
第一個引數是指明在哪幅影象上繪製輪廓;image為三通道才能顯示輪廓
第二個引數是輪廓本身,在Python中是一個list;
第三個引數指定繪製輪廓list中的哪條輪廓,如果是-1,則繪製其中的所有輪廓。後面的引數很簡單。其中thickness表明輪廓線的寬度,如果是-1(cv2.FILLED),則為填充模式。
接下來我們以這幅圖為例:
現在我們來進行程式碼實戰:
import cv2 import numpy as np img = cv2.imread("contours.png") gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) contour = cv2.findContours(gray,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[0] cv2.drawContours(img,contour,-1,(0,0,255),2) cv2.imshow("res",img) cv2.waitKey(0) cv2.destroyAllWindows()
我們還可以改變引數:
import cv2 import numpy as np img = cv2.imread("contours.png") gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) contour = cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[0] cv2.drawContours(img,contour,-1,(0,0,255),2) cv2.imshow("res",img) cv2.waitKey(0) cv2.destroyAllWindows()v
將RETR_EXTERNAL改為RETR_TREE,改為檢測全部輪廓(之前為檢測外部輪廓):
現在我們也可以對輪廓進行選取,我們需要修改drawContours的引數,程式碼:
import cv2 import numpy as np img = cv2.imread("contours.png") gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) contour = cv2.findContours(gray,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[0] cv2.drawContours(img,contour,1,(0,0,255),2) cv2.imshow("res",img) cv2.waitKey(0) cv2.destroyAllWindows()
通過修改第三個引數我們可以自定義選取哪一個輪廓,這樣很方便我們後期的其他操作。
同樣的,我們還可以計算有幾個輪廓,適用Numpy,我們來看程式碼:
import cv2 import numpy as np img = cv2.imread("contours.png") gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) contour = cv2.findContours(gray,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[0] print(np.array(contour).shape) cv2.drawContours(img,contour,1,(0,0,255),2) cv2.imshow("res",img) cv2.waitKey(0) cv2.destroyAllWindows()
下面的輸出欄會打印出來輪廓的個數,改變引數再次實驗一下:
import cv2 import numpy as np img = cv2.imread("contours.png") gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) contour = cv2.findContours(gray,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)[0] print(np.array(contour).shape) cv2.drawContours(img,contour,1,(0,0,255),2) cv2.imshow("res",img) cv2.waitKey(0) cv2.destroyAllWindows()
本次教程對於輪廓進行了一些基本的介紹,下次我們將介紹一些關於輪廓的其他內容。
天道酬勤 循序漸進 技壓群雄