【翻譯:OpenCV-Python教程】圖像輪廓

⚠️由於自己的拖延症,3.4.3翻到一半,OpenCV發佈了4.0.0了正式版,所以接下來是按照4.0.0翻譯的。

⚠️除了版本之外,其他還是照舊,Image Pyramids,原文這篇比較特殊,有多個小節組成,我把它們合在一起了。

輪廓:入門

目標

什麼是輪廓?

輪廓可以簡單地解釋爲(沿邊界)連接所有的連續點的一條曲線,具有相同的顏色或強度。輪廓是形狀分析和目標檢測、識別的重要工具。

  • 爲了更準確的找到圖像,使用二元圖像。在找輪廓之前,先對原圖應用閾值法或者坎尼邊緣檢測。
  • 從 OpenCV 3.2 開始, findContours() 這個函數不再修改原圖。
  • 在OpenCV中,尋找輪廓就像從黑色背景中尋找白色物體一樣。因此記住,要找的對象應該是白色的而背景應該是黑色的。

讓咱們來看看怎麼在二元圖像上找出輪廓:

import numpy as np
import cv2 as cv
im = cv.imread('test.jpg')
imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

可以看到,cv.findContours() 函數有三個參數,第一個是原圖像,第二個是輪廓檢索模式,第三個是輪廓近似法。每個單獨的輪廓是一個對象邊界點座標(x,y)的Numpy數組。

提示

我們稍後會討論到第二第三參數以及關於層次結構的事情,在那之前,我們對它們給出的值都能獲得一個不錯的效果。

怎麼畫出輪廓?

要畫出輪廓,就要用到 cv.drawContours 函數。它也可以被用來畫任何的形狀,只要你有那一組邊界點。它的第一個參數是原圖,第二個參數是Python list型的輪廓點,第三個參數是輪廓的編號(當你想要畫一個單獨的輪廓時有用,如果要畫出所有輪廓,就傳入-1)。還有其他參數是顏色、粗細等等。

  • 要畫圖一張圖像上所有輪廓
cv.drawContours(img, contours, -1, (0,255,0), 3)
  • 要畫一個單獨的輪廓,比如第四個輪廓:
cv.drawContours(img, contours, 3, (0,255,0), 3)
  • 但大多數情況下,以下的方法更有用:
cnt = contours[4]
cv.drawContours(img, [cnt], 0, (0,255,0), 3)

提示

後兩個方法是相同的,但繼續看下去,你會發現最後這一種更有價值。

輪廓近似法

這是 cv.findContours 函數的第三個參數,它到底是什麼意思呢?

之前我們提到,輪廓是具有相同強度的形狀的邊界。它存儲了形狀邊界(上的點)的那些 (x,y) 座標。但他是否保存了全部完整的邊界(上的點)呢?這就由輪廓近似法這個參數來指定了。

如果你傳入 cv.CHAIN_APPROX_NONE,所有的邊界點都會被保存。但實際上,我們需要所有的點嗎?比方說,你來找一條直線的輪廓。你需要這條直線上的全部的點來表示這條直線嗎?當然不是,我們只需要那條直線的兩個端點就夠了。這就是我們要傳入參數 cv.CHAIN_APPROX_SIMPLE 來做的事。它移除了所有冗餘的點,壓縮了輪廓,從而節約了內存。

以下的矩形圖演示了這個技術。只是在所有輪廓數組點的座標上(用藍色)都畫一個圈。第一張用參數 cv.CHAIN_APPROX_NONE 得到的點(734 points)而第二張圖像顯示了使用參數 cv.CHAIN_APPROX_SIMPLE 得到的點(只有4個點)。看它節約了多少內存!!

none.jpg

 

額外資源

練習

輪廓特徵

目標

在這篇文章中,我們會學習

  • 找出輪廓線的不同特徵,如面積、周長、質心、邊框等
  • 你會遇到大量的與輪廓相關的函數

1. 圖像矩

圖像矩可以幫助你算出一些圖像的特徵,比如物體的質心,物體的面積等等。查看維基百科的頁面,Image Moments

函數 cv.moments() 給出計算的所有圖像矩的字典。看下面:

import numpy as np
import cv2 as cv
img = cv.imread('star.jpg',0)
ret,thresh = cv.threshold(img,127,255,0)
contours,hierarchy = cv.findContours(thresh, 1, 2)
cnt = contours[0]
M = cv.moments(cnt)
print( M )

從這個矩,你可以提取有用的數據,比如面積、質心等等。質心通過這個關係取到:Cx=M10M00 和 Cy=M01M00。這可以按照以下步驟來完成:

cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])

2. 輪廓面積

輪廓面積通過這個函數拿到 cv.contourArea(),或者通過圖像矩 M['m00']

area = cv.contourArea(cnt)

3. 輪廓周長

它也被稱爲弧長。它可以用函數 cv.arcLength() 取到。第二個參數指定了其形狀是否是一個封閉的輪廓(如果傳Trued的話)或者只是一條曲線。

perimeter = cv.arcLength(cnt,True)

4. 輪廓近似法

它把輪廓形狀擬合成另外一個形狀,擬閤中使用的頂點的數量取決於我們指定的精度。這就是道格拉斯普克算法(譯者注:它又叫迭代端點擬合算法,大家可以自行百度)查看維基百科的頁面來了解算法和證明。

爲了理解這東西,假設你試圖在圖像中找到一個正方形,但是由於圖像中的一些問題,沒有得到一個完美的正方形,而是得到了一個“壞的形狀”(如下面的第一幅圖像所示)。現在你可以用這個函數來擬合這個形狀。在這個函數裏,第二個參數稱爲epsilon(就是希臘字母的ε),是從輪廓到近似輪廓的最大距離。這是一個參數就決定了擬合精度。要得到正確的輸出,需要明智地選擇。

epsilon = 0.1*cv.arcLength(cnt,True)
approx = cv.approxPolyDP(cnt,epsilon,True)

以下第二張圖,綠色的線條顯示了epsilon = 10% 時候擬合曲線的長度。而第三圖顯示的是同樣的操作在 epsilon = 1% 時的狀況。而第三個參數則指定了擬合出來的曲線是否要閉合。

approx.jpg

5. 凸包算法

凸包算法會看起來和輪廓近似算法有些相像,但它並非如此(有些情況下兩者可能提供出相同的結果)。函數 cv.convexHull() 檢測曲線的凸面瑕疵並且修正它。通常來說,凸曲線是那些總是向外突出的曲線,或者至少是扁平的曲線。而如果它是內凹的,我們就管他叫凸面瑕疵。例如說,看下面手的圖像,紅色的線條就是這張手圖像的凸包。雙面箭頭標出的就是凸面瑕疵,是凸包與輪廓線的局部最大偏差。

convexitydefects.jpg

關於它的語法有一點需要討論:

hull = cv.convexHull(points[, hull[, clockwise[, returnPoints]]

參數細節:

  • points 是我們傳入的輪廓。
  • hull 是輸出值,通常我們都不管它。
  • clockwise:導向標誌。如果爲 True,輸出的凸包向着順時針方向,否則向着逆時針方向。
  • returnPoints:默認情況下,是True。然後它返回凸包點的座標。如果爲False,則返回與凸包點對應的輪廓點的索引(下標)。

因此,要得到上圖所示的凸包,下面的步驟就足夠了:

hull = cv.convexHull(cnt)

但如果你想要找到凸面瑕疵,你需要傳入 returnPoints = False。爲了理解它,我們將取上面的矩形圖像。首先我找出它的輪廓存入對象cnt。現在我用returnPoints = True找出它的凸包,得到[[234 202]],[[51 202]],[[51 79]],[[234 79]]]這是矩形的四個角點。現在,如果用returnPoints = False做同樣的操作,我得到以下結果:[[129],[67],[0],[142]]。這些是輪廓中相應點的索引(下標)。例如,檢查第一個值:cnt[129] =[[234, 202]],這與(爲True是的)第一個(點)結果相同(其他結果也一樣)。

當我們討論凸面瑕疵時,你會再次看到它。

6. 檢測凸面

這有一個方法來檢測一段曲線是凸還是凹,cv.isContourConvex()。它只返回 True 或者 False。沒啥好多說的。

k = cv.isContourConvex(cnt)

7. 邊框

有兩種類型的矩形邊框。

7.a. 整齊的邊框

它是一個整齊的矩形,不考慮物體的旋轉,因此邊框框出來的區域不會是最小的。它通過cv.boundingRect() 函數來獲取。
令座標 (x,y) 作爲邊框的左上角,並且 (w,h) 作爲他的寬度和高度。

x,y,w,h = cv.boundingRect(cnt)
cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)

7.b. 旋轉後的邊框

Here, bounding rectangle is drawn with minimum area, so it considers the rotation also. The function used is cv.minAreaRect(). It returns a Box2D structure which contains following detals - ( center (x,y), (width, height), angle of rotation ). But to draw this rectangle, we need 4 corners of the rectangle. It is obtained by the function cv.boxPoints()

rect = cv.minAreaRect(cnt)

box = cv.boxPoints(rect)

box = np.int0(box)

cv.drawContours(img,[box],0,(0,0,255),2)

Both the rectangles are shown in a single image. Green rectangle shows the normal bounding rect. Red rectangle is the rotated rect.

boundingrect.png

image

8. Minimum Enclosing Circle

Next we find the circumcircle of an object using the function cv.minEnclosingCircle(). It is a circle which completely covers the object with minimum area.

(x,y),radius = cv.minEnclosingCircle(cnt)

center = (int(x),int(y))

radius = int(radius)

cv.circle(img,center,radius,(0,255,0),2)

circumcircle.png

image

9. Fitting an Ellipse

Next one is to fit an ellipse to an object. It returns the rotated rectangle in which the ellipse is inscribed.

ellipse = cv.fitEllipse(cnt)

cv.ellipse(img,ellipse,(0,255,0),2)

fitellipse.png

image

10. Fitting a Line

Similarly we can fit a line to a set of points. Below image contains a set of white points. We can approximate a straight line to it.

rows,cols = img.shape[:2]

[vx,vy,x,y] = cv.fitLine(cnt, cv.DIST_L2,0,0.01,0.01)

lefty = int((-x*vy/vx) + y)

righty = int(((cols-x)*vy/vx)+y)

cv.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)

fitline.jpg

image

Additional Resources

Exercises

Contour Properties

Here we will learn to extract some frequently used properties of objects like Solidity, Equivalent Diameter, Mask image, Mean Intensity etc. More features can be found at Matlab regionprops documentation.

*(NB : Centroid, Area, Perimeter etc also belong to this category, but we have seen it in last chapter)*

1. Aspect Ratio

It is the ratio of width to height of bounding rect of the object.

 

AspectRatio=WidthHeight

x,y,w,h = cv.boundingRect(cnt)

aspect_ratio = float(w)/h

2. Extent

Extent is the ratio of contour area to bounding rectangle area.

 

Extent=ObjectAreaBoundingRectangleArea

area = cv.contourArea(cnt)

x,y,w,h = cv.boundingRect(cnt)

rect_area = w*h

extent = float(area)/rect_area

3. Solidity

Solidity is the ratio of contour area to its convex hull area.

 

Solidity=ContourAreaConvexHullArea

area = cv.contourArea(cnt)

hull = cv.convexHull(cnt)

hull_area = cv.contourArea(hull)

solidity = float(area)/hull_area

4. Equivalent Diameter

Equivalent Diameter is the diameter of the circle whose area is same as the contour area.

 

EquivalentDiameter=4×ContourAreaπ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾√

area = cv.contourArea(cnt)

equi_diameter = np.sqrt(4*area/np.pi)

5. Orientation

Orientation is the angle at which object is directed. Following method also gives the Major Axis and Minor Axis lengths.

(x,y),(MA,ma),angle = cv.fitEllipse(cnt)

6. Mask and Pixel Points

In some cases, we may need all the points which comprises that object. It can be done as follows:

mask = np.zeros(imgray.shape,np.uint8)

cv.drawContours(mask,[cnt],0,255,-1)

pixelpoints = np.transpose(np.nonzero(mask))

#pixelpoints = cv.findNonZero(mask)

Here, two methods, one using Numpy functions, next one using OpenCV function (last commented line) are given to do the same. Results are also same, but with a slight difference. Numpy gives coordinates in **(row, column)** format, while OpenCV gives coordinates in **(x,y)** format. So basically the answers will be interchanged. Note that, row = x and column = y.

7. Maximum Value, Minimum Value and their locations

We can find these parameters using a mask image.

min_val, max_val, min_loc, max_loc = cv.minMaxLoc(imgray,mask = mask)

8. Mean Color or Mean Intensity

Here, we can find the average color of an object. Or it can be average intensity of the object in grayscale mode. We again use the same mask to do it.

mean_val = cv.mean(im,mask = mask)

9. Extreme Points

Extreme Points means topmost, bottommost, rightmost and leftmost points of the object.

leftmost = tuple(cnt[cnt[:,:,0].argmin()][0])

rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])

topmost = tuple(cnt[cnt[:,:,1].argmin()][0])

bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])

For eg, if I apply it to an Indian map, I get the following result :

extremepoints.jpg

image

Additional Resources

Exercises

  1. There are still some features left in matlab regionprops doc. Try to implement them.

Contours : More Functions

Goal

In this chapter, we will learn about

  • Convexity defects and how to find them.
  • Finding shortest distance from a point to a polygon
  • Matching different shapes

Theory and Code

1. Convexity Defects

We saw what is convex hull in second chapter about contours. Any deviation of the object from this hull can be considered as convexity defect.

OpenCV comes with a ready-made function to find this, cv.convexityDefects(). A basic function call would look like below:

hull = cv.convexHull(cnt,returnPoints = False)

defects = cv.convexityDefects(cnt,hull)

Note

Remember we have to pass returnPoints = False while finding convex hull, in order to find convexity defects.

It returns an array where each row contains these values - [ start point, end point, farthest point, approximate distance to farthest point ]. We can visualize it using an image. We draw a line joining start point and end point, then draw a circle at the farthest point. Remember first three values returned are indices of cnt. So we have to bring those values from cnt.

import cv2 as cv

import numpy as np

img = cv.imread('star.jpg')

img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)

ret,thresh = cv.threshold(img_gray, 127, 255,0)

contours,hierarchy = cv.findContours(thresh,2,1)

cnt = contours[0]

hull = cv.convexHull(cnt,returnPoints = False)

defects = cv.convexityDefects(cnt,hull)

for i in range(defects.shape[0]):

s,e,f,d = defects[i,0]

start = tuple(cnt[s][0])

end = tuple(cnt[e][0])

far = tuple(cnt[f][0])

cv.line(img,start,end,[0,255,0],2)

cv.circle(img,far,5,[0,0,255],-1)

cv.imshow('img',img)

cv.waitKey(0)

cv.destroyAllWindows()

And see the result:

defects.jpg

image

2. Point Polygon Test

This function finds the shortest distance between a point in the image and a contour. It returns the distance which is negative when point is outside the contour, positive when point is inside and zero if point is on the contour.

For example, we can check the point (50,50) as follows:

dist = cv.pointPolygonTest(cnt,(50,50),True)

In the function, third argument is measureDist. If it is True, it finds the signed distance. If False, it finds whether the point is inside or outside or on the contour (it returns +1, -1, 0 respectively).

Note

If you don't want to find the distance, make sure third argument is False, because, it is a time consuming process. So, making it False gives about 2-3X speedup.

3. Match Shapes

OpenCV comes with a function cv.matchShapes() which enables us to compare two shapes, or two contours and returns a metric showing the similarity. The lower the result, the better match it is. It is calculated based on the hu-moment values. Different measurement methods are explained in the docs.

import cv2 as cv

import numpy as np

img1 = cv.imread('star.jpg',0)

img2 = cv.imread('star2.jpg',0)

ret, thresh = cv.threshold(img1, 127, 255,0)

ret, thresh2 = cv.threshold(img2, 127, 255,0)

contours,hierarchy = cv.findContours(thresh,2,1)

cnt1 = contours[0]

contours,hierarchy = cv.findContours(thresh2,2,1)

cnt2 = contours[0]

ret = cv.matchShapes(cnt1,cnt2,1,0.0)

print( ret )

I tried matching shapes with different shapes given below:

matchshapes.jpg

image

I got following results:

  • Matching Image A with itself = 0.0
  • Matching Image A with Image B = 0.001946
  • Matching Image A with Image C = 0.326911

See, even image rotation doesn't affect much on this comparison.

See also

Hu-Moments are seven moments invariant to translation, rotation and scale. Seventh one is skew-invariant. Those values can be found using cv.HuMoments() function.

Additional Resources

Exercises

  1. Check the documentation for cv.pointPolygonTest(), you can find a nice image in Red and Blue color. It represents the distance from all pixels to the white curve on it. All pixels inside curve is blue depending on the distance. Similarly outside points are red. Contour edges are marked with White. So problem is simple. Write a code to create such a representation of distance.
  2. Compare images of digits or letters using cv.matchShapes(). ( That would be a simple step towards OCR )

Contours Hierarchy

Goal

This time, we learn about the hierarchy of contours, i.e. the parent-child relationship in Contours.

Theory

In the last few articles on contours, we have worked with several functions related to contours provided by OpenCV. But when we found the contours in image using cv.findContours() function, we have passed an argument, Contour Retrieval Mode. We usually passed cv.RETR_LIST or cv.RETR_TREE and it worked nice. But what does it actually mean ?

Also, in the output, we got three arrays, first is the image, second is our contours, and one more output which we named as hierarchy (Please checkout the codes in previous articles). But we never used this hierarchy anywhere. Then what is this hierarchy and what is it for ? What is its relationship with the previous mentioned function argument ?

That is what we are going to deal in this article.

What is Hierarchy?

Normally we use the cv.findContours() function to detect objects in an image, right ? Sometimes objects are in different locations. But in some cases, some shapes are inside other shapes. Just like nested figures. In this case, we call outer one as parent and inner one as child. This way, contours in an image has some relationship to each other. And we can specify how one contour is connected to each other, like, is it child of some other contour, or is it a parent etc. Representation of this relationship is called the Hierarchy.

Consider an example image below :

hierarchy.png

image

In this image, there are a few shapes which I have numbered from 0-5. 2 and 2a denotes the external and internal contours of the outermost box.

Here, contours 0,1,2 are external or outermost. We can say, they are in hierarchy-0 or simply they are in same hierarchy level.

Next comes contour-2a. It can be considered as a child of contour-2 (or in opposite way, contour-2 is parent of contour-2a). So let it be in hierarchy-1. Similarly contour-3 is child of contour-2 and it comes in next hierarchy. Finally contours 4,5 are the children of contour-3a, and they come in the last hierarchy level. From the way I numbered the boxes, I would say contour-4 is the first child of contour-3a (It can be contour-5 also).

I mentioned these things to understand terms like same hierarchy level, external contour, child contour, parent contour, first child etc. Now let's get into OpenCV.

Hierarchy Representation in OpenCV

So each contour has its own information regarding what hierarchy it is, who is its child, who is its parent etc. OpenCV represents it as an array of four values : [Next, Previous, First_Child, Parent]

*"Next denotes next contour at the same hierarchical level."*

For eg, take contour-0 in our picture. Who is next contour in its same level ? It is contour-1. So simply put Next = 1. Similarly for Contour-1, next is contour-2. So Next = 2.

What about contour-2? There is no next contour in the same level. So simply, put Next = -1. What about contour-4? It is in same level with contour-5. So its next contour is contour-5, so Next = 5.

*"Previous denotes previous contour at the same hierarchical level."*

It is same as above. Previous contour of contour-1 is contour-0 in the same level. Similarly for contour-2, it is contour-1. And for contour-0, there is no previous, so put it as -1.

*"First_Child denotes its first child contour."*

There is no need of any explanation. For contour-2, child is contour-2a. So it gets the corresponding index value of contour-2a. What about contour-3a? It has two children. But we take only first child. And it is contour-4. So First_Child = 4 for contour-3a.

*"Parent denotes index of its parent contour."*

It is just opposite of First_Child. Both for contour-4 and contour-5, parent contour is contour-3a. For contour-3a, it is contour-3 and so on.

Note

If there is no child or parent, that field is taken as -1

So now we know about the hierarchy style used in OpenCV, we can check into Contour Retrieval Modes in OpenCV with the help of same image given above. ie what do flags like cv.RETR_LIST, cv.RETR_TREE, cv.RETR_CCOMP, cv.RETR_EXTERNAL etc mean?

Contour Retrieval Mode

1. RETR_LIST

This is the simplest of the four flags (from explanation point of view). It simply retrieves all the contours, but doesn't create any parent-child relationship. Parents and kids are equal under this rule, and they are just contours. ie they all belongs to same hierarchy level.

So here, 3rd and 4th term in hierarchy array is always -1. But obviously, Next and Previous terms will have their corresponding values. Just check it yourself and verify it.

Below is the result I got, and each row is hierarchy details of corresponding contour. For eg, first row corresponds to contour 0. Next contour is contour 1. So Next = 1. There is no previous contour, so Previous = -1. And the remaining two, as told before, it is -1.

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

This is the good choice to use in your code, if you are not using any hierarchy features.

2. RETR_EXTERNAL

If you use this flag, it returns only extreme outer flags. All child contours are left behind. We can say, under this law, Only the eldest in every family is taken care of. It doesn't care about other members of the family :).

So, in our image, how many extreme outer contours are there? ie at hierarchy-0 level?. Only 3, ie contours 0,1,2, right? Now try to find the contours using this flag. Here also, values given to each element is same as above. Compare it with above result. Below is what I got :

>>> hierarchy

array([[[ 1, -1, -1, -1],

[ 2, 0, -1, -1],

[-1, 1, -1, -1]]])

You can use this flag if you want to extract only the outer contours. It might be useful in some cases.

3. RETR_CCOMP

This flag retrieves all the contours and arranges them to a 2-level hierarchy. ie external contours of the object (ie its boundary) are placed in hierarchy-1. And the contours of holes inside object (if any) is placed in hierarchy-2. If any object inside it, its contour is placed again in hierarchy-1 only. And its hole in hierarchy-2 and so on.

Just consider the image of a "big white zero" on a black background. Outer circle of zero belongs to first hierarchy, and inner circle of zero belongs to second hierarchy.

We can explain it with a simple image. Here I have labelled the order of contours in red color and the hierarchy they belongs to, in green color (either 1 or 2). The order is same as the order OpenCV detects contours.

ccomp_hierarchy.png

image

So consider first contour, ie contour-0. It is hierarchy-1. It has two holes, contours 1&2, and they belong to hierarchy-2. So for contour-0, Next contour in same hierarchy level is contour-3. And there is no previous one. And its first is child is contour-1 in hierarchy-2. It has no parent, because it is in hierarchy-1. So its hierarchy array is [3,-1,1,-1]

Now take contour-1. It is in hierarchy-2. Next one in same hierarchy (under the parenthood of contour-1) is contour-2. No previous one. No child, but parent is contour-0. So array is [2,-1,-1,0].

Similarly contour-2 : It is in hierarchy-2. There is not next contour in same hierarchy under contour-0. So no Next. Previous is contour-1. No child, parent is contour-0. So array is [-1,1,-1,0].

Contour - 3 : Next in hierarchy-1 is contour-5. Previous is contour-0. Child is contour-4 and no parent. So array is [5,0,4,-1].

Contour - 4 : It is in hierarchy 2 under contour-3 and it has no sibling. So no next, no previous, no child, parent is contour-3. So array is [-1,-1,-1,3].

Remaining you can fill up. This is the final answer I got:

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

And this is the final guy, Mr.Perfect. It retrieves all the contours and creates a full family hierarchy list. It even tells, who is the grandpa, father, son, grandson and even beyond... :).

For examle, I took above image, rewrite the code for cv.RETR_TREE, reorder the contours as per the result given by OpenCV and analyze it. Again, red letters give the contour number and green letters give the hierarchy order.

tree_hierarchy.png

image

Take contour-0 : It is in hierarchy-0. Next contour in same hierarchy is contour-7. No previous contours. Child is contour-1. And no parent. So array is [7,-1,1,-1].

Take contour-2 : It is in hierarchy-1. No contour in same level. No previous one. Child is contour-3. Parent is contour-1. So array is [-1,-1,3,1].

And remaining, try yourself. Below is the full answer:

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

Additional Resources

Exercises


上篇:【翻譯:OpenCV-Python教程】圖像金字塔

下篇:【翻譯:OpenCV-Python教程】圖像金字塔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章