Series Article Directory
Article directory
foreword
A contour can be simply understood as a curve connecting all consecutive points (along object boundaries), which usually have the same color or intensity. Contour is of great significance in image analysis. It is a useful tool for object shape analysis and object detection and recognition, and is an important basis for understanding image semantic information.
This article mainly introduces some important methods for processing object contours in opencv.
1. cv2.findContours()
1.1. Method overview
cv2.findContours()
function is part of the OpenCV library, which is widely used for computer vision tasks. This function is used to detect and find contours (boundaries) in an image.
Usually, in order to improve the accuracy of object contour detection, firstly, the color image or grayscale image should be processed into a binary image (grayscale image) or the original image should be filtered once using Canny
the edge detection algorithm, so that the contour information can not be lost. Under the premise of reducing the complexity of image semantic information, it is more helpful for us to accurately analyze the outline of objects.
In short, the process of finding contours is more like the process of finding the boundaries of white objects in a black background.
1.2. cv2.findContours()
contours, hierarchy = cv2.findContours(image, mode, method)
- Parameter meaning
imgae
: Single-channel binary image, white is the foreground (binary image or image processed by Canny algorithm)mode
: Contour search modemethod
: contour approximation method
- return value meaning
contours
- A list object containing all contours in the image. Each of the independent contour information is represented by boundary point coordinates ( x , y ) (x, y)(x,y ) stored in a numpy array
[1, 712, 1, 2]
contours.shape[0]
: This represents the total number of contour lines found in the imagecontours[i].shape[0]
: This represents the iiThe number of points for i contours; each contour line consists of a number of points, this dimension gives the length of the contour linecontours[i].shape[1]
: This represents the number of dimensions (coordinates) used to represent each point in the contour; in most cases this will be 2 22 , for each point( x , y ) (x, y)(x,y ) coordinate
hierarchy
- an array containing 4 values about the contour level
[Next, Previous, First Child, Parent]
Next
: the next contour at the same level as the current contourPrevious
: The previous contour at the same level as the current contourFirst_Child
: the first sub-contour of the current contourParent
: the parent contour of the current contour
- an array containing 4 values about the contour level
1.2.1. Contour retrieval mode
The detailed concept of the contour retrieval mode is as follows:
Contour search mode | effect |
---|---|
cv2.RETR_LIST |
This is the simplest way to find, it does not establish sub-relationships between contours, that is, all contours belong to the same level; output contour information in the form of List |
cv2.RETR_TREE |
Completely establish the hierarchical affiliation of the outline, and output the outline information in a tree structure |
cv2.RETR_EXTERNAL |
Find only the highest-level contours, the outer contours |
cv2.RETR_CCOMP |
Divide all the contours into only 2 levels, either the outer layer or the inner layer; output two layers of contour information, that is, the inner and outer boundaries, the upper layer is the outer boundary, and the inner layer is the boundary information of the inner hole |
Based on the following figure, the contour hierarchy of the image is explained:
There are a total of 8 contours in the figure, 2 and 2a represent the contours of the outer layer and the inner layer respectively, and 3 and 3a are the same, as can be seen from the figure:
- Contours 0, 1, 2 are the outermost contours, we can say they are in the same contour class: class 0
- Contour 2a is the child contour of contour 2, conversely 2 is the parent contour of 2a; contour 2a counts as a level: level 1
- Also 3 is a sub-contour of 2a, and contour 3 is at a level: level 2
- Similarly, 3a is a subcontour of 3
cv2.RETR_RETR_LIST
- This is the simplest way to find, it does not establish a sub-relationship between contours, that is, all contours belong to the same level
- The last two values in the hierarchy [First_Child, Parent] are both − 1 -1−1
- Contour 0 0 since there is no affiliation0 's next entry is1 11 , the next item for $14 is2 22
- If you don't need contour level information, it is more recommended
cv.RETR_LIST
because of better performance
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, 2)
print(hierarchy)
# 结果如下
[[[ 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]]]
cv2.RETR_TREE
Next
- For contour 0, the next contour at the same level as 0 is 1, so Next = 1
- Similarly, for profile 1, Next=2
- For contour 2, there is no next contour at the same level as it, so Next = -1
Previous
- For profile 1, Previous = 0
- For profile 2, Previous = 1
- For contour 2a, there is no previous contour, so Previous = -1
First_Child
- For contour 2, the first child contour is contour 2a, so First_Child = 2a
- For profile 3, First_Child = 3a
Parent
- For profile 2a, the parent profile is 2, Parent = 2
- For profile 2, there is no parent profile, Parent = 0
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, 2)
print(hierarchy)
# 结果如下
[[[ 6 -1 1 -1]
[-1 -1 2 0]
[-1 -1 3 0]
[-1 -1 4 2]
[ 5 -1 -1 3]
[-1 4 -1 3]
[ 7 5 -1 -1]
[-1 6 -1 -1]]]
cv2.RETR_EXTERNAL
- This method only looks for the highest-level contours, that is, it only finds the three 0-level contours we mentioned earlier
contours, hierarchy = cv.findContours(thresh, cv.RETR_EXTERNAL, 2)
print(len(contours), hierarchy, sep='\n')
# 结果如下
3
[[[ 1 -1 -1 -1]
[ 2 0 -1 -1]
[-1 1 -1 -1]]]
cv2.RETR_CCOMP
- Divide all the outlines into only 2 levels, either the outer layer or the inner layer
- In the figure above, 1 in the brackets represents the outer contour, and 2 represents the inner contour
- For profile 2
- Next is 4, Previous is 1
- It has inner contour 3, so First_Child = 3
- But because there are only two levels, it is the outer contour itself, so Parent = -1
contours, hierarchy = cv.findContours(thresh, cv.RETR_CCOMP, 2)
print(hierarchy)
# 结果如下
[[[ 1 -1 -1 -1]
[ 2 0 -1 -1]
[ 4 1 3 -1]
[-1 -1 -1 2]
[ 6 2 5 -1]
[-1 -1 -1 4]
[ 7 4 -1 -1]
[-1 6 -1 -1]]]
1.2.2. Contour approximation method
contour approximation method | effect |
---|---|
cv2.CHAIN_APPROX_NONE |
Store all boundary points |
cv2.CHAIN_APPROX_SIMPLE |
The horizontal, vertical and diagonal line segments in the contour are not saved, only the corner points of the contour are saved |
cv2.CHAIN_APPROX_TX89_L1 |
Use teh-Chini approximation algorithm |
cv2.CHAIN_APPROX_TC89_KCOS |
Use teh-Chini approximation algorithm |
- In general, the latter two methods are less common
cv2.CHAIN_APPROX_NONE
See the picture below on the left;cv2.CHAIN_APPROX_SIMPLE
see the picture below on the right
2. cv2.drawContours()
2.1. Method overview
After cv2.findContours()
finding the outline of the object, sometimes it is necessary to visualize the outline of the object to judge whether it meets expectations. At this time, another important method included in opencv is needed cv2.drawContours()
. The outline of the object obtainedcv2.drawContours()
by using can be drawn on the image with the specified color and line width .cv2.findContours()
2.2. cv2.drawContours()
cv2.drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
- Parameter meaning
image
- This is the input image to draw the contour lines
- Usually an image in RGB format, or a grayscale image
contours
- is the list of contour lines you want to draw on the image
- It should be a Python list where each contour is represented as a ( x , y ) (x, y)(x,y ) NumPy array of coordinates
contourIdx
- This parameter specifies the index of the contour to draw
- Usually use -1 to draw all contours
color
- This parameter specifies the color of the outline
- For color images, the color should be specified as a tuple of three integers representing BGR values (note that it is BGR instead of RGB, which is the same as the color image channel read in using
cv2.imread()
the method ) - For grayscale images, the color value is a scalar representing the intensity
thickness
- This parameter specifies the thickness of the outline in pixels
- Use a negative value to fill the outline
3. cv2.contourArea()
3.1. Method overview
cv2.contourArea()
function is a utility function provided by OpenCV to calculate the area of a contour. It takes a contour as input and returns the area of that contour.
3.2. cv2.contourArea()
area = cv2.contourArea(contours, oriented=false)
- Parameter meaning
contours
- input contour to calculate area
- should be a given by ( x , y ) (x, y)(x,y ) coordinates of a single contour represented by a NumPy array
oriented
- For region identifiers. has a default value of false
- If true, the function returns a signed area value, positive or negative depending on the direction of the contour (clockwise or counterclockwise)
- If false, it means return in absolute value.
- return value
area
- is the output variable used to store the area enclosed by the calculated contour
- It is a floating point value representing the area in pixels
3.3. Existing problems
It should be noted that the cv2.contourArea()
calculated area may be slightly smaller than the expected area. This is because cv2.contourArea()
by taking the center points of the boundary pixels of the connected domain and connecting them to form a contour, the boundary pixels of one week will be lost, that is, the obtained The area is a circle less than the real area
For example, in the figure below, the real area is 4 × 4 = 16 4 \times 4 = 164×4=16 , and cv2.contourArea()
only3 × 3 = 9 3 \times 3 = 93×3=9
Therefore, cv2.contourArea()
it is possible to calculate the area of some contours as 0, as shown in the figure below
A simple workaround is
rect = cv2.minAreaRect(contours) #最小外接矩形
box = cv2.boxPoints(rect)
box = np.int0(box)
area = cv2.contourArea(box)
Summarize
This article mainly records the processing functions related to the label outline encountered by some bloggers during the experiment recently. If there is a need later, the related functions will continue to be updated.