1. 程式人生 > 其它 >OpenCV-Python系列之輪廓入門

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()

本次教程對於輪廓進行了一些基本的介紹,下次我們將介紹一些關於輪廓的其他內容。

天道酬勤 循序漸進 技壓群雄