Opencv foundation 47 find image contour cv2.findContours() detailed explanation

What is Image Contour?

Image contour refers to the continuous curve of the edge of the object in the image. In computer vision and image processing, contours are commonly used to detect objects, segment images, and extract object features.

The image contour is composed of a series of consecutive pixels, which are located on the boundary of the object. Silhouettes are characterized by the position of the boundary between the object and the background, and thus can be used to represent the shape and structure of the object. Contours can be closed or open, depending on the shape of the object.

What is the application scenario of image contour?

Image contours play an important role in many application scenarios, some common application scenarios are listed below:

Object Detection and Recognition : Image contours can be used to detect and localize objects in an image. By detecting the outline of an object, different objects in an image can be identified and classified.

Image Segmentation : Contours can be used to segment different regions or objects in an image. By extracting the outline of the object, the image can be divided into multiple different parts for further analysis and processing.

Medical image analysis : In medical images, contours can be used to label structures such as organs, lesions, or cells. This has important implications for diagnosis and treatment decisions.

Industrial automation : In industrial automation, contours can be used to detect product defects, measure dimensions, and position components, enabling automated production and quality control.

Robot vision : Robots can use image contours to perceive the environment and objects, thereby achieving tasks such as autonomous navigation and grasping objects.

Computer Aided Design (CAD) : In the field of CAD, image contours can be used to obtain geometric information from actual objects for modeling and design on a computer.

Virtual and Augmented Reality : Image silhouettes can be used to track objects in real time, allowing virtual objects to interact with the actual scene to create a more realistic virtual or augmented reality experience.

Image reconstruction and 3D modeling : Image reconstruction and 3D modeling can be performed by using the outline of the object to generate a three-dimensional object model.

Although edge detection can detect edges, the edges are discontinuous, and the detected edges are not a whole. The image contour refers to a whole formed by connecting edges for subsequent calculations.
OpenCV provides a function to find the contour of an image 函数 cv2.findContours(). This function can find the contour information in the image, and the function cv2.drawContours() can draw the contour.
The image contour is a very important feature information in the image. Through the operation of the image contour, we can obtain the size, position, direction and other information of the target image.

Find image contours: findContours function

The syntax format of the function cv2.findContours() is:

image, contours, hierarchy = cv2.findContours( image, mode, method)

The return value in the formula is:

  • image: Consistent with the original image image in the function parameter.
  • contours: The returned contours.
  • hierarchy: Topological information (contour hierarchy) of the image.

The parameters in the formula are:

  • image: the original image. 8-bit single-channel image, all non-zero values ​​are treated as 1, and all zero values ​​are left unchanged. That is to say, the grayscale image will be automatically processed into a binary image. In actual operation, functions such as threshold value processing can be used in advance to process the image of the contour to be searched into a binary image as required.
  • mode: Contour retrieval mode.
  • method: The approximation method for the contour.

The return value and parameters of the function cv2.findContours() have rich meanings, and the above return values ​​and parameters are explained one by one below.

1. The return value image
The return value is consistent with the parameter image, which is the original input image. In OpenCV 4.X, this return value has been cancelled. In OpenCV 4.X, the function cv2.findContours() has only two return values, and its syntax format is:

contours, hierarchy = cv2.findContours( image, mode, method)

2. Return value contours
This return value returns a set of contour information, and each contour is composed of several points. For example, contours[i] is the i-th contour (subscripts start from 0), and contours[i][j] is the j-th point within the i-th contour.

Figure 12-1 shows an example of the extracted contours. The function cv2.findContours() extracts the three contours in the left image, and each contour is composed of several pixels.

insert image description here
The following briefly introduces the basic properties of contours according to Figure 12-1.

(1) type attribute
The type attribute of the return value contours is a list type, and each element of the list is a contour of the image, represented by the ndarray structure in Numpy.
For example, use the following statement to get the type of contours:

print (type(contours))

The result is <class 'list'>.

Use the following statement to get the type of each element in contours:

print (type(contours[0]))

The result is <class 'numpy.ndarray'>.

(2) Number of contours
Use the following statement to get the number of contours:

print (len(contours))

The result is "3", which means that in Figure 12-1, there are 3 contours.

(3) Number of points per contour

Each contour is composed of several pixel points, the number of points is not fixed, and the specific number depends on the shape of the contour.
For example, the number of points in each contour can be obtained by using the following statement:

print (len(contours[0])) #打印第 0 个轮廓的长度(点的个数):4
print (len(contours[1])) #打印第 1 个轮廓的长度(点的个数):60
print (len(contours[2])) #打印第 2 个轮廓的长度(点的个数):184

(4) Points in the contour
Using the following statement, you can get the position attribute of the specific point in the 0th contour in the contour:

print (contours[0]) #打印第 0 个轮廓中的像素点

contours[0] corresponds to the point of the rectangular outline in the lower left corner of the right figure in Figure 12-1, and the output results are as follows:

[[[ 79 270]]
[[ 79 383]]
[[195 383]]
[[195 270]]]
  1. Contours within the return value hierarchy
    image may be located in different positions. For example, one contour is inside another contour. In this case,
    we refer to the outer contour as the parent contour and the inner contour as the child contour . According to the above relationship classification, a parent-child relationship is established between all contours in an image.

From the relationship between contours, it is possible to determine how a contour is connected to other contours. For example, determine whether a contour is a child contour of a certain contour, or a parent contour of a certain contour. The above-mentioned relationship is called a hierarchy (organizational structure), and the return value hierarchy contains the above-mentioned hierarchical relationship.
Each contour contours[i] corresponds to 4 elements to illustrate the hierarchical relationship of the current contour. Its form is:

[Next,Previous,First_Child,Parent]

The meaning of each element in the formula is:

  • Next: The index number of the next contour.

  • Previous: Index number of the previous contour.

  • First_Child: The index number of the first child contour.

  • Parent: The index number of the parent contour.

If the relationship corresponding to each of the above parameters is empty, that is, when there is no corresponding relationship, the value corresponding to the parameter is set to "-1".
Use the print statement to see the value of the hierarchy:

print(hierarchy)

It should be noted that the hierarchical structure of the contour is determined by the parameter mode. That is to say, using different modes, the number of contours obtained is different, and the obtained hierarchy is also different.

  1. Parameter image
    This parameter represents the input image, which must be an 8-bit single-channel binary image. In general, the image is processed into a binary image and then used as the image parameter.

  2. Parameter mode
    The parameter mode determines the extraction method of the contour, specifically as follows:

  • cv2.RETR_EXTERNAL: Only detect outer contours.
  • cv2.RETR_LIST: No hierarchical relationship is established for the detected contours.
  • cv2.RETR_CCOMP: Retrieves all contours and organizes them into a two-level hierarchy. The upper layer is the outer boundary, and the lower layer is the inner hole boundary. If there is another connected object inside the inner hole, then the boundary of this object is still
    at the top level.
  • cv2.RETR_TREE: Create an outline of a hierarchical tree structure.

The four situations are briefly described below.

(1) cv2.RETR_EXTERNAL (only detect the outer contour)

For example, only two outer contours are detected in Figure 12-2, and the serial numbers of the contours are indicated by the numbers in the figure.

insert image description here
Use the print statement to see the value of the hierarchy:

print(hierarchy) [[[ 1 -1 -1 -1] [-1 0 -1 -1]]]

in:

  • The output value "[ 1 -1 -1 -1]" represents the level of the 0th contour.
  • The following contour of it (that is, the 0th contour) is the 1st contour, so the value of the 1st element is "1".
  • Its previous contour does not exist, so the value of the 2nd element is "-1".
  • It has no subcontours, so the value of the 3rd element is "-1".
  • It has no parent outline, so the value of the 4th element is "-1".
  • The output value "[-1 0 -1 -1]" indicates the level of the first contour.
  • The following contour of it (ie the 1st contour) does not exist, so the value of the 1st element is "-1".
  • Its previous contour is the 0th contour, so the value of the 2nd element is "0".
  • It has no subcontours, so the value of the 3rd element is "-1".
  • It has no parent outline, so the value of the 4th element is "-1".
    At this point, the relationship between the contours is:

insert image description here
(2) cv2.RETR_LIST (no hierarchical relationship is established for the detected contours)

For example, three contours are detected in Figure 12-3, and the serial numbers of each contour are indicated by the numbers in the figure.

insert image description here
Using the print statement, you can view the value of the hierarchy:

print(hierarchy) [[[ 1 -1 -1 -1] [ 2 0 -1 -1] [-1 1 -1 -1]]]

in:

  • The output value "[ 1 -1 -1 -1]" represents the level of the 0th contour.

  • The following contour of it (that is, the 0th contour) is the 1st contour, so the value of the 1st element is "1".

  • Its previous contour does not exist, so the value of the 2nd element is "-1".

  • It has no subcontours, so the value of the 3rd element is "-1".

  • It has no parent outline, so the value of the 4th element is "-1".

  • The output value "[2 0 -1 -1]" indicates the level of the first contour.

  • The following contour of it (the 1st contour) is the 2nd contour, so the value of the 1st element is "2".

  • Its previous contour is the 0th contour, so the value of the 2nd element is "0".

  • It has no subcontours, so the value of the 3rd element is "-1".

  • It has no parent outline, so the value of the 4th element is "-1".

  • The output value "[-1 1 -1 -1]" indicates the level of the second contour.

  • The following contour of it (ie the 2nd contour) does not exist, so the value of the 1st element is "-1".

  • Its previous contour is the 1st contour, so the value of the 2nd element is "1".

  • It has no subcontours, so the value of the 3rd element is "-1".

  • It has no parent outline, so the value of the 4th element is "-1".
    It can be seen from the above analysis that when the parameter mode is cv2.RETR_LIST, there is no parent-child relationship between the contours.

At this point, the relationship between the contours is:

insert image description here
(3) cv2.RETR_CCOMP (build two levels of contours)

When the parameter mode is cv2.RETR_CCOMP, two levels of contours are established. The upper layer is the outer boundary, and the lower layer is the inner hole boundary.

For example, three contours are detected in Figure 12-4, and the serial numbers of each contour are indicated by the numbers in the figure.

insert image description here
Use the print statement to see the value of the hierarchy:

print(hierarchy)
[[[ 1 -1 -1 -1]
 [-1 0 2 -1]
 [-1 -1 -1 1]]]

in:

  • The output value "[ 1 -1 -1 -1]" represents the level of the 0th contour.
    The following contour of it (that is, the 0th contour) is the 1st contour, so the value of the 1st element is "1".
    Its previous contour does not exist, so the value of the 2nd element is "-1".
    It has no subcontours, so the value of the 3rd element is "-1".
    It has no parent outline, so the value of the 4th element is "-1".

  • The output value “[-1 0 2 -1]” indicates the level of the first contour.
    The following contour of it (ie the 1st contour) does not exist, so the value of the 1st element is "-1".
    Its previous contour is the 0th contour, so the value of the 2nd element is "0".
    Its 1st child contour is the 2nd contour, so the value of the 3rd element is "2".
    It has no parent outline, so the value of the 4th element is "-1".

  • The value "[-1 -1 -1 1]" indicates the level of the second contour.
    The following contour of it (ie the 2nd contour) does not exist, so the value of the 1st element is "-1".
    Its previous contour also does not exist, so the value of the 2nd element is "-1".
    It has no subcontours, so the value of the 3rd element is "-1".
    Its parent contour is the 1st contour, so the value of the 4th element is "1".
    At this point, the contour relationship is:

insert image description here

(4) cv2.RETR_TREE (build the outline of a hierarchical tree structure)

For example, three contours are detected in Figure 12-5, and the serial numbers of each contour are indicated by the numbers in the figure.

insert image description here
Use the print statement to see the value of the hierarchy:

print(hierarchy)
[[[ 1 -1 -1 -1]
 [-1 0 2 -1]
 [-1 -1 -1 1]]]

in:

  • The output value "[ 1 -1 -1 -1]" represents the level of the 0th contour.
    The following contour of it (that is, the 0th contour) is the 1st contour, so the value of the 1st element is "1".
    Its previous contour does not exist, so the value of the 2nd element is "-1".
    It has no subcontours, so the value of the 3rd element is "-1".
    It has no parent outline, so the value of the 4th element is "-1".

  • The output value “[-1 0 2 -1]” indicates the level of the first contour.
    The following contour of it (ie the 1st contour) does not exist, so the value of the 1st element is "-1".
    Its previous contour is the 0th contour, so the value of the 2nd element is "0".
    Its 1st child contour is the 2nd contour, so the value of the 3rd element is "2".
    Its parent profile does not exist, so the value of the 4th element is "-1".

  • The output value "[-1 -1 -1 1]" indicates the level of the second contour.
    The following contour of it (ie the 2nd contour) does not exist, so the value of the 1st element is "-1".
    Its previous contour does not exist, so the value of the 2nd element is "-1".
    Its subcontour does not exist, so the value of the third element is "-1".
    Its parent contour is the 1st contour, so the value of the 1st element is "1

At this point, the relationship between the contours is:

insert image description here
It should be noted that there are only two layers of contours in this example , so the hierarchical structures obtained by using the parameters cv2.RETR_CCOMP and cv2.RETR_TREE are consistent . When there are multiple layers of contours, using the parameter cv2.RETR_CCOMP will also get a hierarchy with only two layers; and using the parameter cv2.RETR_TREE will get a structure with multiple layers.

6. Parameter method
The parameter method determines how to express the outline, which can be the following values:

  • cv2.CHAIN_APPROX_NONE: Store all contour points, and the pixel position difference between two adjacent points does not exceed 1, that is, max(abs(x1-x2), abs(y2-y1))=1.
  • cv2.CHAIN_APPROX_SIMPLE: Compress elements in the horizontal direction, vertical direction, and diagonal direction, and only retain the end point coordinates of this direction. For example, in extreme cases, a rectangle only needs 4 points to hold the outline information.
  • cv2.CHAIN_APPROX_TC89_L1: Use a flavor of the teh-Chinl chain approximation algorithm.
  • cv2.CHAIN_APPROX_TC89_KCOS: uses a flavor of the teh-Chinl chain approximation algorithm.

For example, in Figure 12-6, the left image is the contour stored with the parameter value cv2.CHAIN_APPROX_NONE, which saves every point in the contour; the right image is the contour stored with the parameter value cv2.CHAIN_APPROX_SIMPLE, and only the points on the boundary are saved. four points.

insert image description here
When using the function cv2.findContours() to find image contours, you need to pay attention to the following issues:

  • The source image to be processed must be a grayscale binary image. Therefore, under normal circumstances, it is necessary to perform threshold segmentation
    or edge detection processing on the image in advance, and then use it as a parameter after obtaining a satisfactory binary image.
  • In OpenCV, it is all about finding white objects from black backgrounds. Therefore, the object must be white and the background must
    be black.
  • In OpenCV 4.x, the function cv2.findContours() has only two return values.

Code example:

import cv2
o = cv2.imread('lena.png')
cv2.imshow("original",o)
gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
#
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
image,contours, hierarchy = cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

print("contours=\n",contours)
print("hierarchy=\n",hierarchy)

After running this code, you will find an error, because I am using the opencv4.5 version.

The error
insert image description here
prompts that in OpenCV 4.x, the function cv2.findContours() only has two return values

The new code is as follows:

import cv2
o = cv2.imread('contours.bmp')

gray = cv2.cvtColor(o,cv2.COLOR_BGR2GRAY)
#
ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

print("hierarchy=\n",hierarchy)

The result of the operation is as follows:

hierarchy=
 [[[ 1 -1 -1 -1]
  [ 2  0 -1 -1]
  [-1  1 -1 -1]]]

Original image:

You can apply the previous explanations to analyze the meaning of the value, such as:

The output value " [ 1 -1 -1 -1] " indicates the level of the 0th contour.
The following contour of it (that is, the 0th contour) is the 1st contour, so the value of the 1st element is "1".
Its previous contour does not exist, so the value of the 2nd element is "-1".
It has no subcontours, so the value of the 3rd element is "-1".
It has no parent outline, so the value of the 4th element is "-1".

Try to understand
[ 2 0 -1 -1]
[-1 1 -1 -1]
insert image description here

Guess you like

Origin blog.csdn.net/hai411741962/article/details/132165910