原文鏈接:http://www.juzicode.com/opencv-python-findcontours-drawcontours
返回Opencv-Python教程
圖像輪廓用來描述圖像中連續的點,它們有同樣的顏色和灰度級。為了更精確地進行檢測,在查找輪廓前需要先將圖像做二值化處理或者使用canny邊沿檢測。在OpenCV中輪廓檢測只查找白色目標,黑色背景會被忽略。
contours,hierarchy=cv2.findContours(image,mode,method[,contours[,hierarchy[,offset]]])
mode的名稱和含義:
mode含義 cv2.RETR_EXTERNAL只提取外部輪廓,設置hierarchy[i][2]=hierarchy[i][3]=-1 cv2.RETR_LIST提取所有輪廓,不包含輪廓間的層次關系 cv2.RETR_CCOMP提取所有輪廓,包含2層層次關系,頂層是外圍邊界,底層是內部hole。如果有多層嵌套,仍然按照2層組織。 cv2.RETR_TREE按照完整的層次關系組織 cv2.RETR_FLOODFILLmethod 的名稱和含義:
method含義cv2.CHAIN_APPROX_NONE存儲所有的邊間點,不管是垂直方向、水平方向或者對角線方向cv2.CHAIN_APPROX_SIMPLE垂直方向、水平方向或對角線方向只保留終點,比如一個長方形就只包含4個頂點cv2.CHAIN_APPROX_TC89_L1使用teh-Chini近似算法cv2.CHAIN_APPROX_TC89_KCOS使用teh-Chini近似算法下面是一個查找輪廓的例子,讀入圖像,灰度化後再進行二值化,然後調用findContours()查找輪廓:
import numpy as np
import cv2
print('VX公眾號: 桔子code / juzicode.com')
#讀入圖像、灰度、二值化
img_src = cv2.imread('..\\samples\\picture\\contours1.bmp')
img_gray = cv2.cvtColor(img_src, cv2.COLOR_BGR2GRAY)
val, img_bin = cv2.threshold(img_gray,127,255, cv2.THRESH_BINARY)
#cv2.imwrite('contours-bin.bmp',img_bin)
#查找輪廓
contours, hierarchy=cv2.findContours(img_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE )
print('contours:',contours)
print('type(contours):',type(contours))
print('len(contours):',len(contours))
print('type(contours[0]):',type(contours[0]))
print('contours[0].shape:',contours[0].shape)
print('hierarchy:',hierarchy)
print('type(hierarchy):',type(hierarchy))
print('len(hierarchy):',len(hierarchy))
print('hierarchy.shape:',hierarchy.shape)
運行結果:
VX公眾號: 桔子code / juzicode.com
contours: [array([[[159, 150]],
[[159, 241]],
[[307, 241]],
[[307, 150]]], dtype=int32), array([[[330, 28]],
[[330, 100]],
[[434, 100]],
[[434, 28]]], dtype=int32), array([[[ 23, 20]],
[[ 23, 114]],
[[172, 114]],
[[172, 20]]], dtype=int32)]
type(contours): <class 'list'>
len(contours): 3
type(contours[0]): <class 'numpy.ndarray'>
contours[0].shape: (4, 1, 2)
hierarchy: [[[ 1 -1 -1 -1]
[ 2 0 -1 -1]
[-1 1 -1 -1]]]
type(hierarchy): <class 'numpy.ndarray'>
len(hierarchy): 1
hierarchy.shape: (1, 3, 4)
contours是找到的輪廓列表,是由n個輪廓組成的list,每個輪廓是一個numpy數組,它的shape為(m,1,2),m為輪廓構成的像素的個數,每個點有2個數值,分別為x和y坐標。
hierarchy的shape為(1,n,4),n對應contours的個數n,所以要訪問第i個輪廓的hierarchy時用hierarchy[0][i]表示。每個hierarchy的元素有4個值組成,依次為next,previous,first child和parent,表示下一個節點,上一個節點,第一個子節點,父節點。
drawContours(image,contours,contourIdx,color[,thickness[,lineType[,hierarchy[,maxLevel[,offset]]]]])->image
下面這個例子查找輪廓後依次繪制輪廓:
import numpy as np
import cv2
print('VX公眾號: 桔子code / juzicode.com')
#讀入圖像、灰度、二值化
img_src = cv2.imread('..\\samples\\picture\\contours1.bmp')
cv2.imshow('img_src',img_src)
img_gray = cv2.cvtColor(img_src, cv2.COLOR_BGR2GRAY)
val, img_bin = cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY)
#查找輪廓
contours, hierarchy=cv2.findContours(img_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE )
print('len(contours):',len(contours))
#繪制輪廓
for ind in range(len(contours)):
cv2.drawContours(img_src, contours, ind, (0,0,255), 3)
cv2.imshow('con',img_src)
cv2.waitKey()
運行結果:
還可以將contourIdx設置為-1,一次性繪制所有輪廓:
#設置為-1,繪制所有輪廓
cv2.drawContours(img_src, contours, -1, (0,0,255), 3)
cv2.imshow('con',img_src)
cv2.waitKey()
設置offset參數:
cv2.drawContours(img_src, contours, -1, (0,0,255), 3, offset=(10,10))
繪制的邊框整體偏移了offset個像素: