輪廓發現
是基於圖像邊緣提取的基礎,尋找對象輪廓的方法,所以邊緣提取的閾值選定會影響最終輪廓的發現
相關API
findContours 發現輪廓
drawContours繪制輪廓
操作步驟
1.轉換圖像為二值化圖像:threshold方法或者canny邊緣提取獲取的都是二值化圖像
2.通過二值化圖像尋找輪廓:findContours
3.描繪輪廓:drawContours
一:使用直接使用閾值方法threshold方法獲取二值化圖像來選擇輪廓
def contours_demo(image):
dst = cv.GaussianBlur(image,(9,9),15) #高斯模糊,消除噪聲
gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY) #先變灰度圖像
ret, binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU) #獲取二值圖像
cv.imshow("binary image",binary)
# cloneImage,contours,heriachy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE) #RETR_TREE包含檢測內部
cloneImage,contours,heriachy = cv.findContours(binary,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE) #RETR_EXTERNAL檢測外部輪廓
for i, contour in enumerate(contours):
# cv.drawContours(image,contours,i,(0,0,255),2) #繪制輪廓
cv.drawContours(image,contours,i,(0,0,255),-1) #填充輪廓
print(i)
cv.imshow("detect contours",image)
src = cv.imread("./lk.png") #讀取圖片
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE) #創建GUI窗口,形式為自適應
cv.imshow("input image",src) #通過名字將圖像和窗口聯系
contours_demo(src)
cv.waitKey(0) #等待用戶操作,里面等待參數是毫秒,我們填寫0,代表是永遠,等待用戶操作
cv.destroyAllWindows() #銷毀所有窗口


二:使用canny邊緣檢測獲取二值化圖像
def contours_demo(image):
binary = edge_demo(image)
cloneImage,contours,heriachy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE) #RETR_TREE包含檢測內部
for i, contour in enumerate(contours):
# cv.drawContours(image,contours,i,(0,0,255),2)
cv.drawContours(image,contours,i,(0,0,255),-1)
print(i)
cv.imshow("detect contours",image)
def edge_demo(image):
dst = cv.GaussianBlur(image,(3,3),0)
gray = cv.cvtColor(dst,cv.COLOR_BGR2GRAY) #先變灰度圖像
edge_output = cv.Canny(gray,50,108)
cv.imshow("detect contours",edge_output)
return edge_output
src = cv.imread("./lk.png") #讀取圖片
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE) #創建GUI窗口,形式為自適應
cv.imshow("input image",src) #通過名字將圖像和窗口聯系
contours_demo(src)
cv.waitKey(0) #等待用戶操作,里面等待參數是毫秒,我們填寫0,代表是永遠,等待用戶操作
cv.destroyAllWindows() #銷毀所有窗口

相關知識補充
(一)findContours尋找輪廓
cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
def findContours(image, mode, method, contours=None, hierarchy=None, offset=None): # real signature unknown; restored from __doc__
1.image:輸入圖像,圖像必須為8-bit單通道圖像,圖像中的非零像素將被視為1,0像素保留其像素值,故加載圖像后會自動轉換為二值圖像。可以通過threshold和canny獲取

RETR_EXTERNAL:表示只檢測最外層輪廓,對所有輪廓設置hierarchy[i][2]=hierarchy[i][3]=-1
RETR_LIST:提取所有輪廓,並放置在list中,檢測的輪廓不建立等級關系
RETR_CCOMP:提取所有輪廓,並將輪廓組織成雙層結構(two-level hierarchy),頂層為連通域的外圍邊界,次層位內層邊界
RETR_TREE:提取所有輪廓並重新建立網狀輪廓結構
RETR_FLOODFILL:官網沒有介紹,應該是洪水填充法

CHAIN_APPROX_NONE:獲取每個輪廓的每個像素,相鄰的兩個點的像素位置差不超過1
CHAIN_APPROX_SIMPLE:壓縮水平方向,垂直方向,對角線方向的元素,值保留該方向的重點坐標,如果一個矩形輪廓只需4個點來保存輪廓信息
CHAIN_APPROX_TC89_L1和CHAIN_APPROX_TC89_KCOS使用Teh-Chinl鏈逼近算法中的一種
返回值:
ret = cv.findContours(binary, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
cloneImage,contours,heriachy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE) #RETR_TREE包含檢測內部
返回一個元組,內部有三個元素
<class 'numpy.ndarray'>
<class 'list'>
<class 'numpy.ndarray'>
第一個返回值:cloneImage是我們傳入的二值化圖像
第二個返回值:contours是一個列表,是輪廓本身,含有輪廓上面的各個點的位置信息
第三個返回值:heriachy是每條輪廓對應的屬性
(二)drawContours繪制輪廓
cv.drawContours(image,contours,i,(0,0,255),2)
cv.drawContours(image,contours,i,(0,0,255),-1)
def drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None): # real signature unknown; restored from __doc__
1.image:輸入輸出圖像,Mat類型即可
2.contours:使用findContours檢測到的輪廓數據,每個輪廓以點向量的形式存儲
3.contourIdx:繪制輪廓的只是變量,如果為負值則繪制所有輸入輪廓
4.color:輪廓顏色
5.thickness:繪制輪廓所用線條粗細度,如果值為負值,則在輪廓內部繪制