[OpenCV-Python] 21 Contours in OpenCV

OpenCV-Python: IV Image Processing in OpenCV

21 Contours in OpenCV

21.1 Getting to know the outline

Goal
  • Understand what is a contour
  • Learn to find contours, draw contours, etc.
  • Functions: cv2.findContours(), cv2.drawContours()

21.1.1 What is a contour

The contour can be simply thought of as a curve connecting continuous points (connected to the boundary) together, with the same color or grayscale. Contours are useful in shape analysis and object detection and recognition.
  • To be more accurate, use a binarized image. Before looking for the contour, thresholding or Canny boundary detection is required.
  • The function for finding contours will modify the original image. If you want to use the original image or image after finding the contour, you should store the original image in other variables.
  • In OpenCV, finding contours is like super white objects on a black background. You should remember that the object you are looking for should be white and the background should be black.
Let us see how to find contours in a binary image: the
  function cv2.findContours() has three parameters, the first is the input image, the second is the contour retrieval mode, and the third is the contour approximation method. There are three return values, the first is the image, the second is the contour, and the third is the (contour) tomographic structure. The contour (the second return value) is a Python list that stores all the contours in the image. Each contour is a Numpy array containing the coordinates of the object boundary point (x, y).
Note: We will introduce the second and third parameters and the hierarchy in detail later. Until then, the parameter values ​​used in the example are applicable to all images.

21.1.2 How to draw contours

The function cv2.drawContours() can be used to draw contours. It can draw any shape according to the boundary points you provide. Its first parameter is the original image, and the second parameter is the contour, a Python list. The third parameter is the index of the contour (useful when drawing independent contours, when set to -1, all contours are drawn). The next parameters are the color and thickness of the outline, etc.
Draw all the contours on one image:

import numpy as np
import cv2
im = cv2.imread('test.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
绘制独立轮廓,如第四个轮廓:
img = cv2.drawContour(img, contours, -1, (0,255,0), 3)
但是大多数时候,下面的方法更有用:
img = cv2.drawContours(img, contours, 3, (0,255,0), 3)

Note: The results of the last two methods are the same, but the knowledge behind will tell you that the last method is more useful.

21.1.3 Approximation method of contour

This is the third parameter of the function cv2.findCountours(). What does it mean?
We have mentioned above that the contour is a boundary with the same gray value. It will store all (x, y) coordinates on the boundary of the shape. But do you need to store all these boundary points? This is what this parameter tells the function cv2.findContours.
If this parameter is set to cv2.CHAIN_APPROX_NONE, all boundary points will be stored. But do we really need so many points? For example, when the boundary we are looking for is a straight line. Do you need all the points on the line to represent the line? No, we only need the two end points of this line. This is what cv2.CHAIN_APPROX_SIMPLE does. It removes all redundant points on the contour, compresses the contour, and saves memory costs. We use the rectangle in the figure below to demonstrate this technique. Draw a blue circle on each coordinate in the contour list. The first figure shows the effect of using cv2.CHAIN_APPROX_NONE, a total of 734 points. The second graph is the result of using cv2.CHAIN_APPROX_SIMPLE, which has only 4 points. See his power!

contour

21.2 Contour features

Goal
  • Find different features of the contour, such as area, perimeter, center of gravity, bounding box, etc.
  • You will learn a lot of contour related functions

21.2.1 Moments

The moment of the image can help us calculate the centroid, area, etc. of the image. For more information, please check Wikipedia Image Moments.
The function cv2.moments() returns the calculated moments in the form of a dictionary. as follows:

import cv2
import numpy as np

img = cv2.imread('star.jpg',0)
ret,thresh = cv2.threshold(img,127,255,0)
contours,hierarchy = cv2.findContours(thresh, 1, 2)

cnt = contours[0]
M = cv2.moments(cnt)
print M

Based on the values ​​of these moments, we can calculate the center of gravity of the object: C_x = \frac{M_{10}}{M_{00}}andC_y = \frac{M_{01}}{M_{00}}

#This can be done as follows:
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])

1.2.2 Contour area

The area of ​​the contour can be calculated using the function cv2.contourArea(), or the moment (0th order moment), M['m00'].

area = cv2.contourArea(cnt)

21.2.3 Contour circumference

Also called arc length. It can be calculated using the function cv2.arcLength(). The second parameter of this function can be used to specify whether the shape of the object is closed (True) or open (a curve).

perimeter = cv2.arcLength(cnt,True)

21.2.4 Contour approximation    approximates
  the contour shape to another contour shape composed of fewer points. The number of points of the new contour is determined by the accuracy set by us. The Douglas-Peucker algorithm used, you can go to Wikipedia for more details of this algorithm.
To help understand, suppose we want to find a rectangle in an image, but due to various reasons of the image, we cannot get a perfect rectangle, but a "bad shape" (as shown in the figure below).
Now you can use this function to approximate this shape (). The second parameter of this function is called epsilon, which is the maximum distance from the original contour to the approximate contour. It is an accuracy parameter. Choosing a good epsilon is very important to get satisfactory results.

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

Below, the green line in the second picture is the approximate contour obtained when epsilon = 10%, and the third picture is the approximate contour obtained when epsilon = 1%. The third parameter sets whether the arc is closed.

Contour Approximation

21.2.5 Convex hull

The convex hull is similar to the contour, but different, although in some cases they give the same result.
  The function cv2.convexHull() can be used to detect whether a curve has convexity defects and correct the defects. Generally speaking, the convexity curve is always convex, at least flat. If there is a recess, it is called a convex defect. For example, the hand in the picture below. The red curve shows the convex hull of the hand, and the convex defect is marked by the double arrow.

Convex Hull
There are a few more explanations about his grammar:

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

Parameters:
  • points the contour we want to pass in
  • hull output, usually not required
  • clockwise direction signs. If set to True, the output convex hull is clockwise. Otherwise, it is counterclockwise.
  • The default value of returnPoints is True. It will return the coordinates of the point on the convex hull. If set to False, the point on the contour corresponding to the convex hull point will be returned.
To obtain the convex hull of the above figure, the following command is sufficient:

hull = cv2.convexHull(cnt)

But if you want to get convexity defects, you need to set returnPoints to False. Taking the above rectangle as an example, first we find his contour cnt. Now I set returnPoints to True to find the convex hull, and I get the following values:
[[[234 202]], [[ 51 202]], [[ 51 79]], [[234 79]]], which is actually rectangular Four corner points.
Now set returnPoints to False, the result I get is [[129],[ 67],[ 0],[142]]. They are the index of the contour points. For example: cnt[129] = [[234,202]], which is the same as the first value of the result we got earlier.

You and we will encounter these in the convex test.

21.2.6 Convexity detection

The function cv2.isContourConvex() can be used to detect whether a curve is convex or not. It can only return True or False. it's not a big deal.

k = cv2.isContourConvex(cnt)

21.2.7 Bounding rectangle

There are two types of bounding rectangles.
  Straight bounding rectangle is a straight rectangle (that is, a rectangle without rotation). It does not consider whether the object is rotated. So the area of ​​the bounding rectangle is not the smallest. You can use the function cv2.boundingRect() to find it.
(X, y) are the coordinates of the upper left corner of the rectangle, (w, h) are the width and height of the rectangle.

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

Rotated bounding rectangle This bounding rectangle has the smallest area because it takes into account the rotation of the object. The function used is cv2.minAreaRect(). What is returned is a Box2D structure, which contains the coordinates (x, y) of the upper left corner of the rectangle, the width and height (w, h) of the rectangle, and the rotation angle. But to draw this rectangle requires 4 corner points of the rectangle, which can be obtained by the function cv2.boxPoints().

rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
im = cv2.drawContours(im,[box],0,(0,0,255),2)

The two bounding rectangles are shown in the figure below, where the green one is a straight rectangle and the red one is a rotated rectangle.

Bounding Rectangle

1.2.8 Minimum circumscribed circle

The function cv2.minEnclosingCircle() can help us find the circumscribed circle of an object.
  It is the smallest area of ​​any circle that can include the object.

(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
img = cv2.circle(img,center,radius,(0,255,0),2)

Minimum Enclosing Circle

21.2.9 Ellipse fitting

The function used is cv2.ellipse(), and the return value is actually the inscribed circle of the rotated bounding rectangle.

ellipse = cv2.fitEllipse(cnt)
im = cv2.ellipse(im,ellipse,(0,255,0),2)

Fitting an Ellipse

21.2.10 Straight line fitting

We can fit a straight line based on a set of points, and we can also fit a straight line to the white points in the image.

rows,cols = img.shape[:2]
#cv2.fitLine(points, distType, param, reps, aeps[, line ]) → line
#points – Input vector of 2D or 3D points, stored in std::vector<> or Mat.
#line – Output line parameters. In case of 2D fitting, it should be a vector of
#4 elements (likeVec4f) - (vx, vy, x0, y0), where (vx, vy) is a normalized
#vector collinear to the line and (x0, y0) is a point on the line. In case of
#3D fitting, it should be a vector of 6 elements (like Vec6f) - (vx, vy, vz,
#x0, y0, z0), where (vx, vy, vz) is a normalized vector collinear to the line
#and (x0, y0, z0) is a point on the line.
#distType – Distance used by the M-estimator
#distType=CV_DIST_L2
#ρ(r) = r2 /2 (the simplest and the fastest least-squares method)
#param – Numerical parameter ( C ) for some types of distances. If it is 0, an optimal value
#is chosen.
#reps – Sufficient accuracy for the radius (distance between the coordinate origin and the
#line).
#aeps – Sufficient accuracy for the angle. 0.01 would be a good default value for reps and
#aeps.
[vx,vy,x,y] = cv2.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
img = cv2.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)

Fitting a Line

21.3 The nature of contours

In this section, we will learn to extract some frequently used object features. You can find more image features in the Matlab regionprops documentation.

21.3.1 Aspect ratio   The aspect ratio of the
  bounding rectangle
      Aspect ; Ratio = \frac{Width}{Height}

x,y,w,h = cv2.boundingRect(cnt)
aspect_ratio = float(w)/h

21.3.2 Extent

The ratio of the area of ​​the outline to the area of ​​the bounding rectangle.
      Extent = \frac{Object ; Area}{Bounding ; Rectangle ; Area}

area = cv2.contourArea(cnt)
x,y,w,h = cv2.boundingRect(cnt)
rect_area = w*h
extent = float(area)/rect_area

21.3.3 Solidity

The ratio of the contour area to the convex hull area.
      Solidity = \frac{Contour ; Area}{Convex ; Hull ; Area}

area = cv2.contourArea(cnt)
hull = cv2.convexHull(cnt)
hull_area = cv2.contourArea(hull)
solidity = float(area)/hull_area

21.3.4 Equivalent Diameter

The diameter of a circle equal to the outline area
      [The external link image transfer failed, the source site may have an anti-leech mechanism, it is recommended to save the image and upload it directly (img-4u8NRjk9-1611980309052)(http://opencv-python-tutroals. readthedocs.io/en/latest/_images/math/dd455145891023674d52ad7f48d9ff5a2613e49b.png)]

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

21.3.5 Direction

The direction of the object, the following method will also return the length of the major axis and the minor axis

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

21.3.6 Masks and pixels
  Sometimes we need all the pixels that make up the object, we can do this:

mask = np.zeros(imgray.shape,np.uint8)
# 这里一定要使用参数 -1, 绘制填充的的轮廓
cv2.drawContours(mask,[cnt],0,255,-1)
#Returns a tuple of arrays, one for each dimension of a,
#containing the indices of the non-zero elements in that dimension.
#The result of this is always a 2-D array, with a row for
#each non-zero element.
#To group the indices by element, rather than dimension, use:
#transpose(nonzero(a))
#>>> x = np.eye(3)
#>>> x
#array([[ 1., 0., 0.],
# [ 0., 1., 0.],
# [ 0., 0., 1.]])
#>>> np.nonzero(x)
#(array([0, 1, 2]), array([0, 1, 2]))
#>>> x[np.nonzero(x)]
#array([ 1., 1., 1.])
#>>> np.transpose(np.nonzero(x))
#array([[0, 0],
# [1, 1],
# [2, 2]])
pixelpoints = np.transpose(np.nonzero(mask))
#pixelpoints = cv2.findNonZero(mask)
# 官方代码
mask = np.zeros(imgray.shape,np.uint8)
cv2.drawContours(mask,[cnt],0,255,-1)
pixelpoints = np.transpose(np.nonzero(mask))
#pixelpoints = cv2.findNonZero(mask)

Here we use two methods, the first method uses the Numpy function, and the second method uses the OpenCV function. The result is the same, but still a bit different. The coordinates given by Numpy are in the
form of (row, colum) . The format given by OpenCV is in the form of (x, y). So these two results are basically interchangeable. row=x, colunm=y.

21.3.7 Maximum and minimum values ​​and their positions

We can use the mask image to get these parameters.

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

21.3.8 Average color and average gray

We can also use the same mask to find the average color or average gray of an object

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

21.3.9 Pole

The top, bottom, left, and right point of an 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]

As shown below:

Extreme Points

21.4 Contours: more functions

Goal
We want to learn
  • Convex defects and how to find convex defects
  • Find the shortest distance from a certain point to a polygon
  • Matching principles and codes of different shapes

21.4.1 Convex defect

We have learned the convex hull of the contour before, and any depression on the object is called a convex defect. There is a function cv.convexityDefect() in OpenCV that can help us find convex defects. The function call is as follows:

hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)

Note: If you want to find convex defects, when using the function cv2.convexHull to find the convex hull, the parameter returnPoints must be False.
It will return an array in which the value contained in each row is [start point, end point, furthest point, approximate distance to furthest point]. We can show it on a picture. We connect the start and end points with a green line and draw a circle at the farthest point. Remember that the first three values ​​of the returned result are the index of the contour point.
So we have to look for them in the contour points.

import cv2
import numpy as np

img = cv2.imread('star.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(img_gray, 127, 255,0)
contours,hierarchy = cv2.findContours(thresh,2,1)
cnt = contours[0]

hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.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])
    cv2.line(img,start,end,[0,255,0],2)
    cv2.circle(img,far,5,[0,0,255],-1)

cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

The results are as follows:

Convexity Defects

21.4.2 Point Polygon Test

Find the shortest distance from a point in the image to the contour of an object. If the point is outside the contour, the
return value is negative. If it is on the contour, the return value is 0. If it is inside the contour, the return value is positive.

Let's take the point (50, 50) as an example:

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

The third parameter of this function is measureDist. If set to True, the shortest distance will be calculated. If it is False, only the positional relationship between this point and the contour will be judged (the return value is +1, -1, 0).

Note: If you don't need to know the specific distance, it is recommended that you set the third parameter to False, which will increase the speed by 2 to 3 times.

21.4.3 Shape matching

The function cv2.matchShape() can help us compare the similarity of two shapes or contours. If the return value is smaller, the match is better. It is calculated based on the Hu moment. The different methods are explained in the documentation.
Let's try to compare the following graphs:

import cv2
import numpy as np

img1 = cv2.imread('star.jpg',0)
img2 = cv2.imread('star2.jpg',0)

ret, thresh = cv2.threshold(img1, 127, 255,0)
ret, thresh2 = cv2.threshold(img2, 127, 255,0)
contours,hierarchy = cv2.findContours(thresh,2,1)
cnt1 = contours[0]
contours,hierarchy = cv2.findContours(thresh2,2,1)
cnt2 = contours[0]

ret = cv2.matchShapes(cnt1,cnt2,1,0.0)
print ret

The results I got are:
  • A matches itself 0.0
  • A matches B 0.001946
  • A matches C 0.326911

Have you seen it? The rotation that happened in time does not have a great impact on the matching result.
Note: Hu moment is a linear combination of normalized central moments. The reason for this is to be able to obtain a moment function representing a certain feature of the image. These moment functions are mapped to certain changes such as scaling, rotation, and mirroring (except h1) Has no deformation. This paragraph is taken from the Chinese version of "Learning OpenCV".

21.5 Hierarchical structure of contours

Goal
  Now we have to learn the hierarchical structure of contours, such as the parent-child relationship between contours.

Principle
  In the previous content, we use the function cv2.findContours to find the contour. We need to pass in a parameter: the contour extraction mode (Contour_Retrieval_Mode). We always set it to cv2.RETR_LIST or cv2.RETR_TREE, the effect is okay. But what do they represent?
  At the same time, the result we get contains 3 arrays, the first image, the second is the contour, and the third is the hierarchical structure. But we have never used a hierarchy. What is the hierarchy used for?
  What is the relationship between the hierarchical structure and the contour extraction mode?
  This is what we are going to talk about in this section.

21.5.1 What is a hierarchy

Usually we use the function cv2.findContours to find an object in the picture. Sometimes objects may be located in different locations. In other cases, one shape is inside another shape. In this case, we call the outer shape the parent and the inner shape the child. According to the classification in this way, a parent-child relationship is established between all contours in an image. In this way, we can determine how a contour is connected to other contours, such as whether it is a child contour or a parent contour. This relationship becomes the organizational structure. The
following diagram is a simple example:

Hierarchy Representation
In this image, I number these shapes 0-5. 2 and 2a represent the outer and inner contours of the outermost rectangle, respectively.
Here the edge contours 0, 1, 2 are on the outside or the outermost edge. We can call them (organizational structure) level 0, which simply means they belong to the same level.

Next contour 2a. We treat it as a sub-contour of contour 2. It becomes the first level (organizational structure). Similarly, contour 3 is a sub-contour of contour 2, and becomes the third level (organization structure). The final contour 4 and 5 are sub-contours of contour 3a and become (organization structure) level 4 (the last level). Numbering these shapes in this way, we can say that contour 4 is a sub-contour of contour 3a (and of course contour 5 is also).
I say so much to explain the hierarchy, outer contour, child contour, parent contour, child contour, etc.
Now let's enter OpenCV.

21.5.2 Hierarchy in OpenCV

No matter what the hierarchy is, each outline contains its own information: who is the parent, who is the child, etc. OpenCV uses a four-element array representation. [Next, Previous, First_Child, Parent].
Next represents the next profile in the same level of organizational structure.
Take contour 0 in the above figure as an example, contour 1 is his Next. Similarly, the Next of contour 1 is 2, and Next=2.
What about contour 2? There is no Next at the same level. At this time Next=-1. The Next of contour 4 is 5, so its Next=5.

Previous represents the previous contour in the same level structure.
As before, the Previous of contour 1 is contour 0, and the Previous of contour 2 is contour 1. Contour 0 has no Previous, so Previous=-1.

First_Child represents its first child profile.
There is no need to explain again, the sub-contour of contour 2 is 2a. So its First_Child is 2a. What about contour 3a? It has two sub-profiles. But we only need the first sub-contour, so it is contour 4 (sorted from top to bottom, from left to right).

Parent represents its parent profile.
It is the opposite of First_Child. The parent contour of contours 4 and 5 is contour 3a. And the parent contour of contour 3a is 3.

Note: If there is no parent or child, it is -1.
Now we understand the outline organization structure in OpenCV. Let's learn about the contour retrieval mode in OpenCV based on the picture above.
What does cv2.RETR_LIST,cv2.RETR_TREE,cv2.RETR_CCOMP,cv2.RETR_EXTERNAL mean?

21.5.3 Contour search mode

RETR_LIST

From an explanatory point of view, this should be the simplest. It just extracts all the contours without creating any parent-child relationship. In other words, "everyone is equal", they belong to the same level of organizational profile.
So in this case, the third and fourth numbers of the organizational structure array are both -1. However, it is obvious that Next and Previous must have corresponding values, you can try and see for yourself.
The following is the result I got, each row is the organizational structure details of the corresponding outline. For example, the first row corresponds to contour 0. The next contour is 1, so Next=1. There are no other contours in front, so Previous=0. The next two parameters are -1, which is the same as we just said.

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

If you don't care about the relationship between the contours, this is a very good choice.

RETR_EXTERNAL

If you choose this mode, only the outermost contour will be returned, and all sub-contours will be ignored.
So using this mode in the above figure will only return the outermost contour (level 0): contour 0, 1, 2. Here are the results I got when I chose this mode:

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

When you only want to get the outermost contour, you can choose this mode. This is useful in some situations.

RETR_CCOMP

In this mode, all contours are returned and the contours are divided into two-level organization structure. For example, the outer contour of an object is the first-level organizational structure. The outline of the cavity inside the object is the second-level organizational structure, and the outline of any object in the cavity is the first-level organizational structure. The hollow organizational structure is level 2.
Imagine an image with white characters on a black background. The number 0 in the image is the number 0. The outer boundary of 0 belongs to the first-level organizational structure, and the interior of 0 belongs to the second-level organizational structure.
We can briefly introduce the following figure as an example. We have numbered these outlines with red numbers and green numbers for their organizational structure. The sequence is the same as that of OpenCV detecting contours.

CCOMP Hierarchy

Now we consider contour 0, its organizational structure is level 1. There are two holes 1 and 2, which belong to the second-level organizational structure. So for contour 0, the next (Next) belonging to the same level of organizational structure is contour 3, and there is no Previous. Its Fist_Child is contour 1, and its organizational structure is 2. Since it is level 1, there is no parent profile. Therefore, its organizational structure array is [3, -1, 1, -1].
It is now contour 1, which is the second level. The next contour at the same level is 2. There is no Previous and no Child, (because it is level 2 so there is a parent profile) the parent profile is 0. So the array is [2, -1, -1, 0].
Contour 2: It is the second level. There is no Next in the same level of organizational structure. Previous is contour 1. There is no child, and the parent contour is 0, so the array is [-1, 1, -1, 0]
contour 3: it is the first level. In the same level of organizational structure, Next is 5. Previous is contour 0. The child is 4 and there is no parent contour, so the array is [5, 0, 4, -1] contour 4: it is the second level. There is no Next in the same level of organizational structure. There is no Previous, no children, and the parent profile is 3, so the array is [-1, -1, -1, 3]

Here is the 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]]])

RETR_TREE

It's finally the last one, and it's the most perfect one. In this mode, all contours will be returned and a complete list of organizational structures will be created. It will even tell you who is the grandfather, father, son, grandson, etc.

Take the above figure as an example. Use this mode to reorder and analyze the results returned by OpenCV. The red numbers are the serial numbers of the borders, and the green is the organizational structure.

CCOMP Hierarchy

The organizational structure of contour 0 is 0, and Next is 7 in the same level, and there is no Previous. The child profile is 1, and there is no parent profile. So the array is [7, -1, 1, -1].
The organizational structure of contour 1 is 1, there is no other in the same level, and there is no Previous. The child profile is 2 and the parent profile is 0. So the array is [-1, -1, 2, 0].
Try to calculate the rest for yourself.

Here is the result:

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

For more information, please pay attention to the official account:
img

Guess you like

Origin blog.csdn.net/yegeli/article/details/113423022