欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

OpenCV-Python實(shí)現(xiàn)輪廓檢測(cè)實(shí)例分析

 更新時(shí)間:2018年01月05日 09:37:23   作者:Daetalus  
這篇文章主要介紹了OpenCV-Python實(shí)現(xiàn)輪廓檢測(cè)實(shí)例分析,具有一定借鑒價(jià)值,需要的朋友可以參考下

相比C++而言,Python適合做原型。本系列的文章介紹如何在Python中用OpenCV圖形庫(kù),以及與C++調(diào)用相應(yīng)OpenCV函數(shù)的不同之處。這篇文章介紹在Python中使用OpenCV檢測(cè)并繪制輪廓。

提示:

轉(zhuǎn)載請(qǐng)?jiān)敿?xì)注明原作者及出處,謝謝!

本文介紹在OpenCV-Python中檢測(cè)并繪制輪廓的方法。

本文不介詳細(xì)的理論知識(shí),讀者可從其他資料中獲取相應(yīng)的背景知識(shí)。筆者推薦清華大學(xué)出版社的《圖像處理與計(jì)算機(jī)視覺(jué)算法及應(yīng)用(第2版)》。

輪廓檢測(cè)

輪廓檢測(cè)也是圖像處理中經(jīng)常用到的。OpenCV-Python接口中使用cv2.findContours()函數(shù)來(lái)查找檢測(cè)物體的輪廓。

實(shí)現(xiàn)

使用方式如下:

import cv2 
 
img = cv2.imread('D:\\test\\contour.jpg') 
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) 
 
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 
cv2.drawContours(img,contours,-1,(0,0,255),3) 
 
cv2.imshow("img", img) 
cv2.waitKey(0) 

需要注意的是cv2.findContours()函數(shù)接受的參數(shù)為二值圖,即黑白的(不是灰度圖),所以讀取的圖像要先轉(zhuǎn)成灰度的,再轉(zhuǎn)成二值圖,參見(jiàn)4、5兩行。第六行是檢測(cè)輪廓,第七行是繪制輪廓。

結(jié)果

原圖如下:

檢測(cè)結(jié)果如下:

注意,findcontours函數(shù)會(huì)“原地”修改輸入的圖像。這一點(diǎn)可通過(guò)下面的語(yǔ)句驗(yàn)證:

cv2.imshow("binary", binary) 
contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 
cv2.imshow("binary2", binary) 

執(zhí)行這些語(yǔ)句后會(huì)發(fā)現(xiàn)原圖被修改了。

cv2.findContours()函數(shù)

函數(shù)的原型為

cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])

返回兩個(gè)值:contours:hierarchy。

參數(shù)

第一個(gè)參數(shù)是尋找輪廓的圖像;

第二個(gè)參數(shù)表示輪廓的檢索模式,有四種(本文介紹的都是新的cv2接口):
cv2.RETR_EXTERNAL表示只檢測(cè)外輪廓
cv2.RETR_LIST檢測(cè)的輪廓不建立等級(jí)關(guān)系
cv2.RETR_CCOMP建立兩個(gè)等級(jí)的輪廓,上面的一層為外邊界,里面的一層為內(nèi)孔的邊界信息。如果內(nèi)孔內(nèi)還有一個(gè)連通物體,這個(gè)物體的邊界也在頂層。
cv2.RETR_TREE建立一個(gè)等級(jí)樹(shù)結(jié)構(gòu)的輪廓。

第三個(gè)參數(shù)method為輪廓的近似辦法
cv2.CHAIN_APPROX_NONE存儲(chǔ)所有的輪廓點(diǎn),相鄰的兩個(gè)點(diǎn)的像素位置差不超過(guò)1,即max(abs(x1-x2),abs(y2-y1))==1
cv2.CHAIN_APPROX_SIMPLE壓縮水平方向,垂直方向,對(duì)角線方向的元素,只保留該方向的終點(diǎn)坐標(biāo),例如一個(gè)矩形輪廓只需4個(gè)點(diǎn)來(lái)保存輪廓信息
cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

返回值

cv2.findContours()函數(shù)返回兩個(gè)值,一個(gè)是輪廓本身,還有一個(gè)是每條輪廓對(duì)應(yīng)的屬性。

contour返回值

cv2.findContours()函數(shù)首先返回一個(gè)list,list中每個(gè)元素都是圖像中的一個(gè)輪廓,用numpy中的ndarray表示。這個(gè)概念非常重要。在下面drawContours中會(huì)看見(jiàn)。通過(guò)

print (type(contours)) 
print (type(contours[0])) 
print (len(contours)) 

可以驗(yàn)證上述信息。會(huì)看到本例中有兩條輪廓,一個(gè)是五角星的,一個(gè)是矩形的。每個(gè)輪廓是一個(gè)ndarray,每個(gè)ndarray是輪廓上的點(diǎn)的集合。

由于我們知道返回的輪廓有兩個(gè),因此可通過(guò)

cv2.drawContours(img,contours,0,(0,0,255),3) 

cv2.drawContours(img,contours,1,(0,255,0),3) 

分別繪制兩個(gè)輪廓,關(guān)于該參數(shù)可參見(jiàn)下面一節(jié)的內(nèi)容。同時(shí)通過(guò)

print (len(contours[0])) 
print (len(contours[1])) 

輸出兩個(gè)輪廓中存儲(chǔ)的點(diǎn)的個(gè)數(shù),可以看到,第一個(gè)輪廓中只有4個(gè)元素,這是因?yàn)檩喞胁⒉皇谴鎯?chǔ)輪廓上所有的點(diǎn),而是只存儲(chǔ)可以用直線描述輪廓的點(diǎn)的個(gè)數(shù),比如一個(gè)“正立”的矩形,只需4個(gè)頂點(diǎn)就能描述輪廓了。

hierarchy返回值

此外,該函數(shù)還可返回一個(gè)可選的hiararchy結(jié)果,這是一個(gè)ndarray,其中的元素個(gè)數(shù)和輪廓個(gè)數(shù)相同,每個(gè)輪廓contours[i]對(duì)應(yīng)4個(gè)hierarchy元素hierarchy[i][0]~hierarchy[i][3],分別表示后一個(gè)輪廓、前一個(gè)輪廓、父輪廓、內(nèi)嵌輪廓的索引編號(hào),如果沒(méi)有對(duì)應(yīng)項(xiàng),則該值為負(fù)數(shù)。

通過(guò)

print (type(hierarchy)) 
print (hierarchy.ndim) 
print (hierarchy[0].ndim) 
print (hierarchy.shape) 

得到

3 
2 
(1, 2, 4) 

可以看出,hierarchy本身包含兩個(gè)ndarray,每個(gè)ndarray對(duì)應(yīng)一個(gè)輪廓,每個(gè)輪廓有四個(gè)屬性。

輪廓的繪制

OpenCV中通過(guò)cv2.drawContours在圖像上繪制輪廓。

cv2.drawContours()函數(shù)

cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])

第一個(gè)參數(shù)是指明在哪幅圖像上繪制輪廓;
第二個(gè)參數(shù)是輪廓本身,在Python中是一個(gè)list。
第三個(gè)參數(shù)指定繪制輪廓list中的哪條輪廓,如果是-1,則繪制其中的所有輪廓。后面的參數(shù)很簡(jiǎn)單。其中thickness表明輪廓線的寬度,如果是-1(cv2.FILLED),則為填充模式。繪制參數(shù)將在以后獨(dú)立詳細(xì)介紹。

補(bǔ)充:

寫(xiě)著寫(xiě)著發(fā)現(xiàn)一篇文章介紹不完,所以這里先作為入門(mén)的。更多關(guān)于輪廓的信息有機(jī)會(huì)再開(kāi)一篇文章介紹。

但有朋友提出計(jì)算輪廓的極值點(diǎn)??捎孟旅娴姆绞接?jì)算得到,如下

pentagram = contours[1] #第二條輪廓是五角星 
 
leftmost = tuple(pentagram[:,0][pentagram[:,:,0].argmin()]) 
rightmost = tuple(pentagram[:,0][pentagram[:,:,0].argmin()]) 
 
cv2.circle(img, leftmost, 2, (0,255,0),3)  
cv2.circle(img, rightmost, 2, (0,0,255),3)  

注意!假設(shè)輪廓有100個(gè)點(diǎn),OpenCV返回的ndarray的維數(shù)是(100,1,2)?。?!而不是我們認(rèn)為的(100,2)。切記?。?!人民郵電出版社出版了一本《NumPy攻略:Python科學(xué)計(jì)算與數(shù)據(jù)分析》,推薦去看一下。

更新:關(guān)于pentagram[:,0]的意思

在numpy的數(shù)組中,用逗號(hào)分隔的是軸的索引。舉個(gè)例子,假設(shè)有如下的數(shù)組:

a = np.array([[[3,4]], [[1,2]],[[5,7]],[[3,7]],[[1,8]]]) 

其shape是(5, 1, 2)。與我們的輪廓是相同的。那么a[:,0]的結(jié)果就是:

[3,4], [1,2], [5,7], [3,7], [1,8] 

這里a[:,0]的意思就是a[0:5,0],也就是a[0:5,0:0:2],這三者是等價(jià)的。

回頭看一下,a的shape是(5,1,2),表明是三個(gè)軸的。在numpy的數(shù)組中,軸的索引是通過(guò)逗號(hào)分隔的。同時(shí)冒號(hào)索引“:”表示的是該軸的所有元素。因此a[:,0]表示的是第一個(gè)軸的所有元素和第二個(gè)軸的第一個(gè)元素。在這里既等價(jià)于a[0:5,0]。

再者,若給出的索引數(shù)少于數(shù)組中總索引數(shù),則將已給出的索引樹(shù)默認(rèn)按順序指派到軸上。比如a[0:5,0]只給出了兩個(gè)軸的索引,則第一個(gè)索引就是第一個(gè)軸的,第二個(gè)索引是第二個(gè)軸的,而第三個(gè)索引沒(méi)有,則默認(rèn)為[:],即該軸的所有內(nèi)容。因此a[0:5,0]也等價(jià)于a[0:5,0:0:2]。

再詳細(xì)一點(diǎn),a的全體內(nèi)容為:[[[3,4]],[[1,2]],[[5,7]],[[3,7]],[[1,8]]]。去掉第一層方括號(hào),其中有五個(gè)元素,每個(gè)元素為[[3,4]]這樣的,所以第一個(gè)索引的范圍為[0:5]。注意OpenCV函數(shù)返回的多維數(shù)組和常見(jiàn)的numpy數(shù)組的不同之處!

觀察[[3,4]],我們發(fā)現(xiàn)其中只有一個(gè)元素,即[3,4],第二個(gè)索引為[0:1]。

再去掉一層方括號(hào),我們面對(duì)的是[3,4],有兩個(gè)元素,所以第三個(gè)索引的范圍為[0:2]。

再次強(qiáng)調(diào)一下OpenCVPython接口函數(shù)返回的NumPy數(shù)組和普通的NumPy數(shù)組在組織上的不同之處。

PS:OpenCV-Python討論群——219962286,歡迎大家加入互相探討學(xué)習(xí)。

得到的結(jié)果為如下:

總結(jié)

以上就是本文關(guān)于OpenCV-Python實(shí)現(xiàn)輪廓檢測(cè)實(shí)例分析的全部?jī)?nèi)容,希望對(duì)大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:

簡(jiǎn)單了解OpenCV是個(gè)什么東西

python通過(guò)opencv實(shí)現(xiàn)批量剪切圖片

python+opencv實(shí)現(xiàn)的簡(jiǎn)單人臉識(shí)別代碼示例

如有不足之處,歡迎留言指出。感謝朋友們對(duì)本站的支持!

相關(guān)文章

最新評(píng)論