5 Best Ways to Compute the Area and Perimeter of an Image Contour Using OpenCV Python

πŸ’‘ Problem Formulation: In computer vision, precisely quantifying the shape of objects within an image is a common task. This article addresses the challenge of computing the area and perimeter of image contours using OpenCV with Python. Imagine you have an image with a single prominent object – your goal is to calculate the size (area) and outline length (perimeter) of this object. The input would be the image and the output, numeric values representing the area and perimeter of the detected contour.

Method 1: FindContours and ContourArea

This method involves using the findContours() function to detect contours in an image, followed by the contourArea() function to compute the area of the contour. This approach is suitable for finding the area of distinct objects in binary images.

Here’s an example:

import cv2

# Read the image and convert to grayscale
image = cv2.imread('object.png')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

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

# Calculate the area of the first contour
area = cv2.contourArea(contours[0])
print("Area of the contour:", area)

Output: Area of the contour: 15000.5

In this code, findContours() returns a list of contours found in the grayscale image. The contourArea() function then computes the area of the first contour in that list, which is printed to the console.

Method 2: ApproxPolyDP and Contour Perimeter

With approxPolyDP(), one can approximate the contour to a more manageable shape, and then use the arcLength() function to compute the perimeter, which can be particularly useful when you need a smoother contour for perimeter calculation.

Here’s an example:

import cv2

# Read the image and convert to grayscale
image = cv2.imread('object.png')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

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

# Approximate the contour and calculate the perimeter
epsilon = 0.01 * cv2.arcLength(contours[0], True)
approx_contour = cv2.approxPolyDP(contours[0], epsilon, True)
perimeter = cv2.arcLength(approx_contour, True)
print("Perimeter of the contour:", perimeter)

Output: Perimeter of the contour: 510.2

After detecting contours using findContours(), the code uses approxPolyDP() to simplify the contour shape. The arcLength() function then computes the perimeter of this approximated contour.

Method 3: Bounding Rectangle Area and Perimeter

Using the bounding rectangle’s area and perimeter is a fast way to get an approximation of the contour’s dimensions. The boundingRect() method can provide a non-rotated rectangle that encloses the contour.

Here’s an example:

import cv2

# Read the image and convert to grayscale
image = cv2.imread('object.png')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

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

# Calculate the bounding rectangle, then compute area and perimeter
x, y, w, h = cv2.boundingRect(contours[0])
area = w * h
perimeter = 2 * (w + h)
print("Bounding rectangle area:", area)
print("Bounding rectangle perimeter:", perimeter)

Output: Bounding rectangle area: 16000
Bounding rectangle perimeter: 520

This snippet calculates the bounding rectangle for the contour using boundingRect(). The area and perimeter are then calculated using the width and height of the rectangle.

Method 4: Fitting an Ellipse

If the object is circular or elliptical, fitting an ellipse with fitEllipse() can provide a more accurate measurement. This function returns the rotated rectangle in which the ellipse is inscribed.

Here’s an example:

import cv2

# Read the image and convert to grayscale
image = cv2.imread('object.png')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

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

# Fit an ellipse to the contour and calculate the area
ellipse = cv2.fitEllipse(contours[0])
area = 3.14 * ellipse[1][0] * ellipse[1][1] / 4 # Approximating Pi for simplicity
print("Area of the fitted ellipse:", area)

Output: Area of the fitted ellipse: 14526.5

fitEllipse() is used on the detected contour to create an inscribed ellipse. The area of this ellipse is then approximated using the major and minor axes provided by fitEllipse().

Bonus One-Liner Method 5: Simplified Contour Area

For a quick and simplified calculation, directly applying the contourArea() function on the contour detected by findContours() can provide an immediate result.

Here’s an example:

import cv2

# Read the image and convert to grayscale, find contours and calculate area
print("Simplified contour area:", cv2.contourArea(cv2.findContours(cv2.cvtColor(cv2.imread('object.png'), cv2.COLOR_BGR2GRAY), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0][0]))

Output: Simplified contour area: 15000.5

This one-liner demonstrates the power of Python’s concise syntax by chaining function calls to immediately output the area of the first contour detected.

Summary/Discussion

  • Method 1: FindContours and ContourArea. Accurate for binary images with distinct objects. Cannot handle complex or overlapping shapes.
  • Method 2: ApproxPolyDP and Contour Perimeter. Good for getting a smooth contour for perimeter calculations. May oversimplify the contour and lose detail.
  • Method 3: Bounding Rectangle Area and Perimeter. Quick and easy, provides a rough estimate. Not suitable for non-rectangular objects.
  • Method 4: Fitting an Ellipse. Best for elliptical or circular objects, gives a precise area. Not applicable to non-elliptical shapes.
  • Bonus Method 5: Simplified Contour Area. Quick and easy for single use cases. Lacks precision and control over the contour selection.