OpenCV-Python教程:22.輪廓層級(jí)

理論

在前面的關(guān)于輪廓的幾節(jié)里,我們介紹了輪廓相關(guān)的一些函數(shù)。但當(dāng)我們用cv2.findContours()函數(shù)來找輪廓的時(shí)候,我們傳入了一個(gè)參數(shù),Contour Retrieval Mode。我們一般傳的是cv2.RETR_LIST或者cv2.RETR_TREE這樣就可以了。但是這個(gè)參數(shù)實(shí)際是什么意思呢?

并且在輸出時(shí)我們得到了三個(gè)數(shù)組,第一個(gè)是圖像,第二個(gè)是我們的輪廓,第三個(gè)輸出名字是hierarchy。但是我們一直沒用這個(gè)。

什么是層級(jí)?

一般來說我們用cv2.findContours()函數(shù)來檢測(cè)圖像里的目標(biāo),有時(shí)候目標(biāo)在不同的地方,但是在有些情況下,有些圖形在別的圖形里面,就像圖形嵌套,在這種情況下,我們把外面那層圖形叫做parent,里面的叫child。這樣圖形里的輪廓之間就有了關(guān)系。我們可以指定一個(gè)輪廓和其他之間的是如何連接的,這種關(guān)系就是層級(jí)。

看下面的例子:

在這個(gè)圖像里,不同的圖形我標(biāo)注了0-5,2和2a表示了最外層盒子的外部和內(nèi)部輪廓。

這里輪廓0,1,2是外部的。我們可以說他們是hierarchy-0,或者他們是同層級(jí)的。

接下來是contour-2a,可以認(rèn)為是輪廓-2的孩子,或者反過來,contour-2是contour-2a的父親,所以它在hierarchy-1里。類似的contour-3是contour-2的孩子,在下一層級(jí)。最后contour4,5是contour-3a的孩子,它們?cè)谧詈蟮膶蛹?jí)。

OpenCV里的層級(jí)表示

每個(gè)輪廓有他自己的關(guān)于層級(jí)的信息,誰是他的孩子,誰是他的父親等。OpenCV用一個(gè)包含四個(gè)值得數(shù)組來表示:[Next, Previous, First_Child, Parent]

"Next表明同一層級(jí)的下一個(gè)輪廓"

比如,在我們的圖片里的contour-0,水上hi他相同層級(jí)的下一個(gè)輪廓?是contour-1,所以Next=1,對(duì)于Contour-1,下一個(gè)是contour-2,所以Next=2

那對(duì)于contour-2呢?沒有同層級(jí)的下一個(gè)輪廓,所以Next=-1。那么對(duì)于contour-4呢?同層級(jí)的下一個(gè)是contour-5,所以下一個(gè)輪廓是contour-5.Next=5

"Previous指同層級(jí)的前一個(gè)輪廓"

和上面一樣,contour-1的前一個(gè)是contour-0.contour-2的前一個(gè)contour-1.對(duì)于contour-0沒有前序,所以-1

"First_Child指它的第一個(gè)孩子輪廓"

不用解釋,對(duì)于contour-2,孩子是contour-2a,所以這里是contour-2a的索引,contour-3a有兩個(gè)孩子,但我們只取第一個(gè),是contour-4,所以First_Child=4.

"Parent指它的父輪廓索引"

和First_Child相反,contour-4和contour-5的parent都是contour-3a,對(duì)于contour-3a,是contour-3

注意:
如果沒有孩子或者父親,就為-1

我們知道了層級(jí),現(xiàn)在來看OpenCV里的輪廓獲取模式,四個(gè)標(biāo)志cv2.RETR_LIST, cv2.RETR_TREE, cv2.RETR_CCOMP, cv2.RETR_EXTERNAL表示啥?

輪廓獲取模式

1.RETR_LIST

這是最簡單的一個(gè),它獲取所有輪廓,但是不建立父子關(guān)系,他們都是一個(gè)層級(jí)。

所以,層級(jí)屬性第三個(gè)和第四個(gè)字段(父子)都是-1,但是Next和Previous還是有對(duì)應(yīng)值。

下面是結(jié)果,每行是對(duì)應(yīng)輪廓的層級(jí)信息。

>>> hierarchy

array([[[ 1, -1, -1, -1],
[ 2,? 0, -1, -1],
[ 3,? 1, -1, -1],
[ 4,? 2, -1, -1],
[ 5,? 3, -1, -1],
[ 6,? 4, -1, -1],
[ 7,? 5, -1, -1],
[-1,? 6, -1, -1]]])

2.RETR_EXTERNAL

如果用這個(gè)模式,它返回最外層的。所有孩子輪廓都不要,我們可以說在這種情況下,只有家族里最老的會(huì)被照顧,其他都不管。

所以在我們的圖像里,有多少最外層的輪廓呢,有3個(gè),contours 0,1,2

>>>hierarchy
array([[[ 1, -1, -1, -1],
[ 2,? 0, -1, -1],
[-1,? 1, -1, -1]]])

3.RETR_CCOMP

這個(gè)模式獲取所有輪廓并且把他們組織到一個(gè)2層結(jié)構(gòu)里,對(duì)象的輪廓外邊界在等級(jí)1里,輪廓內(nèi)沿(如果有的話)放在層級(jí)2里。如果別的對(duì)象在它里面,里面的對(duì)象輪廓還是放在層級(jí)1里,它的內(nèi)沿在層級(jí)2.

看下面的例子,輪廓的順序?yàn)榧t色,他們的層級(jí)是綠色,

看第一個(gè)輪廓,contour-0,他的層級(jí)是1,他有兩個(gè)洞,contours1和2,他們都屬于層級(jí)2,所以對(duì)于contour-0,Next是contour-3,沒有前序,他的第一個(gè)孩子是contour-1,沒有parent,所以層級(jí)數(shù)組是[3,-1,1,-1]

看contour-1,他在層級(jí)2里,Next是contour-2,沒有前序,沒有孩子,parent是contour-0,所以數(shù)組是[2,-1,-1,0]

同樣對(duì)于contour-2,也在層級(jí)2里,沒有next,前序是contour-1,沒有孩子,parent是contour-0,所以[-1,1,-1,0]。

contour-3:next是contour-5,Previous是contour-0,Child是contour-4,沒有parent,所以[5,0,4,-1]

contour-4:在層級(jí)2里,沒有兄弟,所以沒有Next,沒有Previous,沒有孩子,parent是contour-3,[-1,-1,-1,3]

>>> hierarchy
array([[[ 3, -1,? 1, -1],
[ 2, -1, -1,? 0],
[-1,? 1, -1,? 0],
[ 5,? 0,? 4, -1],
[-1, -1, -1,? 3],
[ 7,? 3,? 6, -1],
[-1, -1, -1,? 5],
[ 8,? 5, -1, -1],
[-1,? 7, -1, -1]]])

4.RETR_TREE

最后,Mr.Perfect。它取回所有的輪廓并且創(chuàng)建完整的家族層級(jí)列表,它甚至能告訴你誰是祖父,父親,兒子,孫子。。

比如把上面的圖形用cv2.RETR_TREE,

對(duì)于contour-0:層級(jí)是0,Next是contour-7,沒有previous,孩子是contour-1,沒有parent,所以[7,-1,1,-1]

contour-1:在層級(jí)1里,沒有同級(jí)的其他輪廓,沒有previous,孩子是contour-2,所以[-1,-1,2,0]

>>> hierarchy
array([[[ 7, -1,? 1, -1],
[-1, -1,? 2,? 0],
[-1, -1,? 3,? 1],
[-1, -1,? 4,? 2],
[-1, -1,? 5,? 3],
[ 6, -1, -1,? 4],
[-1,? 5, -1,? 4],
[ 8,? 0, -1, -1],
[-1,? 7, -1, -1]]])

OpenCV里的直方圖

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容