Skip to content

Tutorials

Real time shape detection – Opencv with Python 3

Access community, courses and source codes
Logo

AI Vision Academy

Access the code of this tutorial, computer vision courses and an exclusive community on AI Vision Academy

  • Access to over 50+ source codes from Pysource.com/blog
  • Dedicated video courses about computer vision
  • Access to an exclusive community of professionals
  • Real-World AI Projects – Get hands-on experience building practical AI Computer Vision solutions with a structured path.
  • Monthly Coaching Calls – get support and any of your questions answered

Subscribe to our newsletter to learn more

In this video tutorial we’re going to see how to detect shapes of geometric figures (like rectangles, triangles and circles) in a live video.

We can detect shapes in real time in this three simple steps:

  1. Detect the objects, removing the background.
  2. Find the contours of the objects detected.
  3. Detect the shape of each of the objects detected, in real time.

1) Detect the objects

Detecting correctly the objects is a crucial part of this project, as If we would like to find their shapes we need to know exactly their boundaries.

It’s possible to use different approaches to detect an object, but as it’s not the goal of this project, we will use a really simple method so mostly we can focuso on the detection of its shape.

If you would like to know more about Color Detection, you can read here the tutorial.

We start by importing the libraries Opencv and Numpy, we create a function nothing that we need later and we load the camera.

import cv2
import numpy as np

def nothing(x):
    # any operation
    pass

cap = cv2.VideoCapture(1)

We create the trackbars in order to change the ranges to detect a specific color in real time.
I will skip the creation part of the trackbars in this code, if you want to know more about trackbars and color detection, check this article

lower_red = np.array([l_h, l_s, l_v])
upper_red = np.array([u_h, u_s, u_v])

mask = cv2.inRange(hsv, lower_red, upper_red)
kernel = np.ones((5, 5), np.uint8)
mask = cv2.erode(mask, kernel)

2) Find contours

Second step once we detected the objects by their colors, we need to find the contours.

If you want to know more about contours, check this article.

Bear in mind that the function to detect contour is different depending on the opencv version you’re using.

Find contours on Opencv 3.x.x

_, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

Find contours on Opencv 4.x.x

contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

3) Detect Shapes

If we consider a contour as a polygon which exactly sorrounds the object, getting its shape, the shape detection is a simple counting of how many points the contour has.

We need to remove as much noise as possible in order to have a clean contour.
So we use the approximation function on line 50.

area = cv2.contourArea(cnt)
approx = cv2.approxPolyDP(cnt, 0.02*cv2.arcLength(cnt, True), True)
x = approx.ravel()[0]
y = approx.ravel()[1]

Later we improve even more the detection, removing all the small dots detected, which are just noise.
We do that by taking contour which have a big area, in this case greater than 400 pixels.

And finally we count the lenght of the contours.
If a contour has 3 points is a triangle, 4 points a rectangle and between 10 and 20 points a circle.

if area > 400:
    cv2.drawContours(frame, [approx], 0, (0, 0, 0), 5)

    if len(approx) == 3:
        cv2.putText(frame, "Triangle", (x, y), font, 1, (0, 0, 0))
    elif len(approx) == 4:
        cv2.putText(frame, "Rectangle", (x, y), font, 1, (0, 0, 0))
    elif 10 < len(approx) < 20:
        cv2.putText(frame, "Circle", (x, y), font, 1, (0, 0, 0))

27 comments

  1. Thanks for all your videos, really it’s so hard to do this, thank you.
    Sir, I am PhD student in the first year, and my subject is detection and tracking in real time perhaps I will do this with infrared imagery, could you give me your email please.

  2. Thanks for this video, really useful.

    How would you modify the code so that you can detect 3 colors and the shapes, so that the output would display for instance “Red recangle” or “Yellow Circle” ?

  3. I’ve been getthing this error.. I hope you can help, thank you!

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    error: OpenCV(4.1.0) ..\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function ‘cv::cvtColor’

    1. It means that the frame is empty.
      Make sure you’re correctly loading the frame.

      try printing the frame and see what you get.

      print(frame)

    2. Here: cap = cv2.VideoCapture(1)
      Change the 1 for a 0 or -1.
      That is the assigned number of your camera. Usually starts counting on 0, for 2nd camera a 1, a 3rd camera a 2, etc. Or it may start on -1.
      cap = cv2.VideoCapture(0)

  4. i got an error
    _, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    ValueError: need more than 2 values to unpack
    i hope you can help thanks

  5. Sir I am looking to detect helix shaped structures(corkscrew shaped) through image processing/computer vision. Will you please guide me with the path which I should follow for doing the same.

  6. Hi Sergio,
    My name is Ger from Holland. The script and explaining is just what i search for.
    But, is it possible to use more colors at the same time.
    If yes, can you explain how to integrate this into the script.

    many thanks in advance,

    Ger

  7. Hello , thanks for the work
    But I get an error
    In _,contrours,_= cv2 …
    In this like
    And the error is
    Value error : not enough values to unpack. ( expected 3 , got 2)

    Can anyone help please

  8. Hi there. Thank you for the code. If may ask how can I change the draw shape that instead of using the actual shape of the object im just going to use rectangle when it detects an object? thank you so much

  9. Thanks for your great work. I am trying to detect an arrow with a dotted/broken line but I am unable. I started with detecting a dotted line using Hough transformation then latter I tried to detect the arrowhead but still, I was unable.

Join the discussion