본문 바로가기
Lecture/OpenCV Master with Python (Beginner)

OpenCV + Python Contour Detection and Labeling - 1

by codingwalks.en 2024. 10. 30.
728x90
반응형

 

Hello. This is codingwalks.

In the field of computer vision, edge detection and labeling are key technologies for image analysis and object recognition. These two technologies can be used to extract the boundaries and shapes of objects in images, and to analyze each object separately. In particular, edge detection using OpenCV and Python is widely used in various industries and research fields, and it allows automated systems to operate more accurately and efficiently.

In this article, we will explain edge detection and labeling techniques in detail using OpenCV functions such as cv2.findContours, cv2.approxPolyDP, cv2.convexHull, and cv2.moments. In addition, we will cover real-world use cases and the limitations and improvements of these techniques to suggest practical applications of edge detection techniques. From beginners to experts in computer vision, this article will provide a wide range of information from the basics to advanced uses of edge detection.


1. Basic Concepts: OpenCV Contour Detection

A contour is a curve that defines the boundary of an object in an image. Since a contour is composed of continuous pixels of the same color or intensity, it is useful for finding the outline of an object. If you find the contour well, you can determine the shape, size, and location of the object. Therefore, the contour plays an important role in computer vision tasks such as image analysis and object recognition.

Basic Concepts of Contour Detection

Contours are detected in binarized images. This is because contour detection is mainly performed on black and white images. Binarization is the process of converting an image to black and white, which is an important preprocessing step in contour detection.

Contour detection example

Main process of contour detection

  1. Image binarization: Before contour detection, use thresholding or edge detection to remove the background of the image and separate the target object.
  2. Contour search: This is the process of detecting the outline of the object in the binarized image. At this time, the outline can have a hierarchical structure and is divided into the internal outline and the external outline of the object.
  3. Contour feature analysis: Features such as area, center, and length can be extracted from the detected outline. This is used in object recognition or analysis.

Utilization of contour detection

Contour detection is used in various computer vision tasks such as image segmentation, object recognition, shape analysis, and motion tracking. For example, you can identify an object based on its appearance or extract a specific area in an image.


2. Find contours: cv2.findContours

The cv2.findContours() function is used to detect contours in OpenCV. This function finds contours in a binarized image and returns a hierarchical structure. This allows us to find not only the outer boundary of an object, but also the inner boundary of the object.

The function structure of cv2.findContours

contours, hierarchy = cv2.findContours(image, mode, method)
  • image: The binarized image to detect the contours. The image must be binarized in advance using cv2.threshold() or cv2.Canny().
  • mode: Sets the contour search method. The main options are:
    • cv2.RETR_EXTERNAL: Detects only the outermost contours.
    • cv2.RETR_LIST: Detects all contours regardless of hierarchy.
    • cv2.RETR_CCOMP: Detects all contours in a two-level hierarchy.
    • cv2.RETR_TREE: Detects all contours in a hierarchy.
  • method: Sets the contour approximation method. The main options are:
    • cv2.CHAIN_APPROX_NONE: Stores all contour points. cv2.CHAIN_APPROX_SIMPLE: Save only the vertices of the contour to save memory.
    • cv2.CHAIN_APPROX_TC89_L1: Approximate the contour points based on the Teh & Chin L1 distance.
    • cv2.CHAIN_APPROX_TC89_KCOS: Approximate the contour points based on the Teh & Chin K-Cosine distance.

Contour Hierarchy

cv2.findContours() function returns a hierarchy along with the contours. The hierarchy is useful to distinguish between the inner and outer contours of an object. For example, a donut-shaped object with a hole inside would have two contours, one for the outer boundary and one for the inner hole.

  • 4 values ​​of hierarchy
    • [Next, Previous, First_Child, Parent]
    • Next: Next contour in the same layer
    • Previous: Previous contour in the same layer
    • First_Child: First contour in the lower layer
    • Parent: Contour in the upper layer

Contour Approximation

cv2.findContours() stores all coordinates along the boundary of the object by default. However, complex contours can consume a lot of memory. Therefore, we can save memory by storing only the vertices of the contour using the CHAIN_APPROX_SIMPLE method.

Comparison of major options for contour detection

  • cv2.RETR_EXTERNAL detects only the outermost contour, which is useful when only the object boundary is needed.
  • cv2.RETR_TREE returns all contours in a hierarchical structure, which is suitable for understanding the structure inside the object.

Example code

import cv2

# Reading and binarizing images
image = cv2.imread('resources/contour.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# Find contours
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Draw contours
cv2.drawContours(image, contours, -1, (0, 255, 0), 2)
cv2.imshow('Contours', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.findContours result image


3. Simplify the outline: cv2.approxPolyDP

The cv2.approxPolyDP() function is used to simplify the outline. It is a method to approximate the outline of an object with fewer points, which is useful for simplifying complex outlines. This function is especially useful for finding the simplified shape of an object through morphological analysis or polygonal approximation of the object.

The function structure of cv2.approxPolyDP

approx = cv2.approxPolyDP(curve, epsilon, closed)
  • curve: The outline (curve) to be approximated. Usually, a specific outline is passed from the outline list found by cv2.findContours().
  • epsilon: This parameter determines how much to approximate the outline, and sets the maximum error for the outline length. A smaller value results in a more accurate approximation, while a larger value results in a greater simplification. Typically, epsilon is set as a ratio of the outline length (e.g. 0.02 * arcLength). 
  • closed: If True, it is treated as a closed outline, and if False, it is treated as an open outline.

Approximation Polygon Algorithm (Douglas-Peucker Algorithm)

The cv2.approxPolyDP() function uses the Douglas-Peucker Algorithm. This algorithm simplifies a curve or polygon by approximating the curve with a small number of points. In this process, the distance between the original curve and the approximated polygon is set to not exceed epsilon.

Importance of Choosing an epsilon Value

The epsilon value determines the accuracy of the polygon approximation. If the value is too small, there is little difference from the original outline, and if it is too large, the outline may be overly simplified and the shape of the object may be distorted. In general, it is appropriate to set the epsilon value to about 2% of the total outline length.

Application Cases

  • Shape Analysis: Simplifying the outline makes it easier to understand the shape of the object. For example, you can understand the basic shape of the object through a polygonal approximation such as a square or triangle.
  • Object Classification: Analyze the shape of an object using approximate polygons and distinguish between regular and irregular shapes.

Practical Applications of Approximate Polygons

cv2.approxPolyDP() is used to analyze geometric features of an object or as a preliminary step for shape recognition. For example, this function is useful when detecting geometric shapes such as squares or triangles.

Example Code

import cv2

# Reading and binarizing images
image = cv2.imread('resources/approxpolydp.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)

# Find contours
contours, _ = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Select one of the outlines and apply an approximate polygon
for contour in contours:
    epsilon = 0.01 * cv2.arcLength(contour, True)
    approx = cv2.approxPolyDP(contour, epsilon, True)
    
    # Draw approximate contours
    cv2.drawContours(image, [approx], -1, (0, 0, 255), 2)

cv2.imshow('Approx PolyDP', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.approxPolyDP result image


4. Convex Hull Detection: cv2.convexHull

Convex hull refers to the smallest convex polygon that encloses a given set of points. This allows us to determine whether an object is convex when analyzing its outline. In OpenCV, we can detect the convex hull of an object using the cv2.convexHull() function.

Function structure of cv2.convexHull

hull = cv2.convexHull(points[, hull[, clockwise[, returnPoints]]])
  • points: A set of points that make up the outline, mainly passing the outline data obtained by cv2.findContours().
  • hull: A variable to store the convex hull.
  • clockwise: If True, the convex hull is generated in a clockwise direction. The default value is False.
  • returnPoints: If True, it returns the point coordinates, and if False, it returns the index of the point.

Differences between Convex Hull and Outline Detection

  • Contour: A line drawn along all boundaries of an object.
  • Convex Hull: The smallest convex polygon that encloses an object, enclosing only the protruding parts of the outline.

Use Cases of Convex Hull

  • Object Shape Analysis: By judging the convexity of an object, you can analyze how complex the shape of the object is. You can use the convex hull to identify the geometric characteristics of the object.
  • Collision Detection: It is used to detect collisions between 2D objects or to find boundaries, and is also widely used in game development and robotics.

Convexity Defects

After obtaining the Convex Hull, the parts where the outline is not convex, that is, the parts that are separated from the convex hull, are called Convexity Defects. By detecting these, you can analyze the uneven parts of the object.

Example Code

import cv2

# Reading and binarizing images
image = cv2.imread('resources/approxpolydp.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# Find contours
contours, _ = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Calculating and Drawing the Convex Hull
for contour in contours:
    hull = cv2.convexHull(contour)
    cv2.drawContours(image, [hull], -1, (0, 0, 255), 2)

cv2.imshow('Convex Hull', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.convexHull result image


5. Calculating the center and area of ​​the outline: cv2.moments

The cv2.moments() function calculates the moments of the outline, and can extract the characteristics of the object such as the center, area, and slope. Moments are values ​​that represent the geometric characteristics of the object, and can be used to find the center point of the object or analyze rotation, etc.

What is a moment?

Moments are numerical expressions of the position, size, and shape of an object by synthesizing values ​​for specific coordinates in the image. Moments are largely divided into spatial moments, central moments, and normalized central moments. These moments can be used to calculate the area, center of gravity, and degree of rotation of the object.

cv2.moments function structure

M = cv2.moments(contour)
  • contour: The outline obtained by cv2.findContours().
  • The returned M is a dictionary representing moments, containing various moment values. 

Key Moment Values

  • M["m00"]: Area, which is the sum of pixels inside the outline. Area of ​​the 2D outline.
  • M["m10"] and M["m01"]: These are the values ​​used to calculate the center of gravity of the outline.
  • M["mu20"], M["mu02"], M["mu11"]: Central moments, which are used to calculate the directionality of the object.

Calculating the Center of Gravity

The center of gravity represents the coordinates of the center of the outline, and can be calculated using moments as follows:

\[C_x = \frac{M[m10]}{M[m00]}, \quad C_y = \frac{M[m01]}{M[m00]}\]​

Here, \(C_x\) and \(C_y\) represent the x and y coordinates of the center of gravity, respectively.

Analysis of the area and center of gravity of an object

The above code is an example of calculating the area and center of gravity of an outline and displaying them on an image. Using moments, you can easily calculate the center coordinates and area of ​​an object.

Applications

  • Tracking the position of an object based on center coordinates: You can detect changes in the position of an object by tracking the center coordinates while the object moves in the image.
  • Analyzing the rotation and orientation of an object: You can use moments to determine the degree of rotation and orientation of an object. This can be used to track or align the rotation direction of an object.

Calculating the inclination

You can analyze the orientation of an object using moments. Using the center moments, you can calculate the angle of orientation, which represents the orientation of an object. This represents the angle by which the object is rotated.

\[\theta = \frac{1}{2} \arctan\left(\frac{2 \cdot M[mu11]}{M[mu20] - M[mu02]}\right)\]

This calculation can be used to determine the direction in which the object is tilted.

Example code: Calculating area and center point

import cv2

# Reading and binarizing images
image = cv2.imread('resources/approxpolydp.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# Find contours
contours, _ = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Calculating moments for the first contour
for contour in contours:
    M = cv2.moments(contour)

    # Calculating area
    area = M["m00"]

    # Calculating center of gravity
    if M["m00"] != 0:
        cx = int(M["m10"] / M["m00"])
        cy = int(M["m01"] / M["m00"])
    else:
        cx, cy = 0, 0

    # Drawing contours and center of gravity
    cv2.drawContours(image, [contour], -1, (0, 255, 0), 2)
    cv2.circle(image, (cx, cy), 5, (0, 0, 255), -1)

cv2.imshow('Contours and Centroid', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.moments result image


The content is getting too long, so I will move on to the next post.

 

OpenCV + Python Contour Detection and Labeling - 2

Hello. This is codingwalks.In this article, I will continue writing from the previous article. OpenCV + Python Contour Detection and Labeling - 1Hello. This is codingwalks.In the field of computer vision, edge detection and labeling are key tech

en.codingwalks.com

 

If you found this post useful, please like and subscribe below. ^^

Buy me a coffee

 

[Codingwalks]에게 송금하기 - AQR

[Codingwalks]에게 송금하기 - AQR

aq.gy

★ All contents are referenced from the link below. ★

 

OpenCV: OpenCV-Python Tutorials

Core Operations In this section you will learn basic operations on image like pixel editing, geometric transformations, code optimization, some mathematical tools etc.

docs.opencv.org

728x90
반응형