Real time shape detection – Opencv with Python 3
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:
- Detect the objects, removing the background.
- Find the contours of the objects detected.
- 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() y = approx.ravel()
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))