Image preprocessing Tricks [1]: Contours

Series 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 Cannythe 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 mode
    • method: 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 image
        • contours[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 line
        • contours[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 contour
        • Previous: The previous contour at the same level as the current contour
        • First_Child: the first sub-contour of the current contour
        • Parent: the parent contour of the current contour

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:

insert image description here
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:

  1. Contours 0, 1, 2 are the outermost contours, we can say they are in the same contour class: class 0
  2. 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
  3. Also 3 is a sub-contour of 2a, and contour 3 is at a level: level 2
  4. 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 -11
    • 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_LISTbecause 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]]]

insert image description here

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

insert image description here

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

insert image description here

  • 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-Chiniapproximation algorithm
cv2.CHAIN_APPROX_TC89_KCOS Use teh-Chiniapproximation algorithm
  • In general, the latter two methods are less common
  • cv2.CHAIN_APPROX_NONESee the picture below on the left; cv2.CHAIN_APPROX_SIMPLEsee the picture below on the right

insert image description here


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

insert image description here

Therefore, cv2.contourArea()it is possible to calculate the area of ​​some contours as 0, as shown in the figure below

insert image description here

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.

Reference blog
Reference blog

Guess you like

Origin blog.csdn.net/HoraceYan/article/details/130816337