How to Detect Shape in OpenCV

Ammar Ali Feb 02, 2024
How to Detect Shape in OpenCV

This tutorial will discuss detecting shapes present in an image using the findContours() and approxPolyDP() functions of OpenCV.

Use the findContours() and approxPolyDP() Functions of OpenCV to Detect Shapes Present in an Image

We can find shapes present in an image using the findContours() and approxPolyDP() function of OpenCV. We can detect shapes depending on the number of corners it has.

For example, a triangle has 3 corners, a square has 4 corners, and a pentagon has 5 corners.

To find the number of corners of a shape, we must first find the given image’s contours using the findContours() function, and then use the approxPolyDP() function to find the number of corners or sides of a shape.

We can find the given image’s contours using the findContours() function of OpenCV, but we must use a binary or black and white image inside the findContours() function.

To convert the given image into binary, we must use the cvtColor() and threshold() function of OpenCV.

The cvtColor() function converts one color space into another, and we will use it to convert the BGR image to grayscale. The threshold() function converts the grayscale image into binary with only two values, 0 and 255.

We must find the length of the output of the approxPolyDP() function to get the number of corners of an image and use the if-else statement to print the shape’s name and the number of corners.

We can also add a different color to each shape using the drawContours() function.

For example, let’s detect the shapes present in a BGR image. See the code below.

import cv2
import numpy as np

img = cv2.imread("shapes.png")
original = img.copy()

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

ROI_number = 0
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for cnt in cnts:
    approx = cv2.approxPolyDP(cnt, 0.01 * cv2.arcLength(cnt, True), True)
    print(len(approx))
    if len(approx) == 5:
        print("Blue = pentagon")
        cv2.drawContours(img, [cnt], 0, 255, -1)
    elif len(approx) == 3:
        print("Green = triangle")
        cv2.drawContours(img, [cnt], 0, (0, 255, 0), -1)
    elif len(approx) == 4:
        print("Red = square")
        cv2.drawContours(img, [cnt], 0, (0, 0, 255), -1)
    elif len(approx) == 6:
        print("Cyan = Hexa")
        cv2.drawContours(img, [cnt], 0, (255, 255, 0), -1)
    elif len(approx) == 8:
        print("White = Octa")
        cv2.drawContours(img, [cnt], 0, (255, 255, 255), -1)
    elif len(approx) > 12:
        print("Yellow = circle")
        cv2.drawContours(img, [cnt], 0, (0, 255, 255), -1)

cv2.imshow("image", img)
cv2.imshow("Binary", thresh)
cv2.waitKey()

Output:

5
Blue = pentagon
6
Cyan = Hexa
8
White = Octa
3
Green = triangle
4
Red = square
14
Yellow = circle

shape detection

The shapes should be white in a binary image, and the background should be black. As you can see, the shapes’ color in the output image is different from the color of shapes in the original image.

Arguments of the findContours() and approxPolyDP() Functions of OpenCV

The first argument of the findContours() function is the binary image, and the second argument is the contour retrieval method.

We use the cv2.RETR_EXTERNAL because we only need the external contours. The third argument is the approximation method used to find the contours.

The first argument of the approxPolyDP() function is the contours of the image. The second is the parameter specifying the approximation accuracy, and the third is used to specify if the approximation curve is closed or not.

The approxPolyDP() function uses the Douglas Peucker algorithm to approximate the contour shape to another shape. The drawContours() function is used to draw the contours.

The first argument of the drawContours() function is the image we want to draw the color. The second argument is the contours, and the third is the color of the contours.

The fourth argument is the line thickness, and if its value is negative, the color will fill the shape.

Author: Ammar Ali
Ammar Ali avatar Ammar Ali avatar

Hello! I am Ammar Ali, a programmer here to learn from experience, people, and docs, and create interesting and useful programming content. I mostly create content about Python, Matlab, and Microcontrollers like Arduino and PIC.

LinkedIn Facebook

Related Article - OpenCV Image