Detecting shapes from an image is one of the coolest things you can perform with Python and OpenCV. There are many methods and techniques available in the OpenCV library to detect shapes in an image, and for most of them, we first find out the edges in the image and then detect its shape.
We can either use canny edge or contours methods to find edges in an image, and then according to the edge detection, we can name the shape.
In this Python tutorial, we will walk you through the different Python scripts to detect shapes in an image using OpenCV. Moreover, we will use the Python OpenCV library and use the contour edge detection method to detect the shapes in the image.
So let's start with installing the OpenCV library for the Python environment.
Install Python OpenCV
OpenCV is one of the most popular Python image processing libraries. We can easily install this library for our Python environment using the following Python pip install terminal command:
pip install opencv-python
For this tutorial, we will be using the following image and detecting the shape from this image only.
shape.png
How to Detect Shapes in Python Using OpenCV?
1) Detect a Circle in an Image Using OpenCV in Python
import cv2 as cv
#import image
image = cv.imread("shape.png")
#convert image into greyscale mode
gray_image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
#find threshold of the image
_, thrash = cv.threshold(gray_image, 240, 255, cv.THRESH_BINARY)
contours, _ = cv.findContours(thrash, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
for contour in contours:
shape = cv.approxPolyDP(contour, 0.01*cv.arcLength(contour, True), True)
x_cor = shape.ravel()[0]
y_cor = shape.ravel()[1]-15
if len(shape) >12:
cv.drawContours(image, [shape], 0, (0,0,255), 4)
cv.putText(image, "Circle", (x_cor, y_cor), cv.FONT_HERSHEY_COMPLEX, 0.5, (0,0,255))
cv.imshow("Shape", image)
cv.waitKey(0)
cv.destroyAllWindows()
Output
Behind the code
-
In the first line of the program, we have imported the OpenCV
cv2
module ascv
. -
The
imread()
method loads the"shape.png"
image in our script. -
The
cv.cvtColor(image, cv.COLOR_BGR2GRAY)
statement converts the loaded BGR image into a grayscale image because we do not need color intensities to detect shapes. -
The
cv.threshold(gray_image, 240, 255, cv.THRESH_BINARY)
function finds out the threshold frequency of the grayscale image,gray_image
, for further image processing.240
is the threshold value, and255
is the maximum threshold value. -
cv.findContours(thrash, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
is the function that will find out all the contours present in the grayscale image based on the thresholds. To know more about the OpenCV counter, click here . - After finding all the contours, we loop over every contour and detect the shape.
-
The
cv.approxPolyDP()
function returns all the polygons curve based on the contour with precision. Both theTrue
parameters specify the close contour and curve. -
ravel()[0]
andravel()[1]
functions return the x and y coordinates of the contour, and we will use these two coordinates to write the shape name. -
The
approxPolyDP()
function returns the approximate curves. Using thelen()
function, we can find out the total number of curves present in that close loop. A circle can have an infinite number of curved edges as arcs, but for this tutorial, we have specified that if the shape has more than 12 curves or edges, it should be treated as a circle. -
The
drawContours(image, [shape], 0, (0,0,255), 4)
function will draw the contours over the original image(0,0,255)
color code and4
border thickness. -
The
putText()
function will write the shape name over the detected shape.
2) Detect Square and Rectangle in an Image Using OpenCV
Similar to the above program, we can find out the square and rectangle shapes in an image. Both squares and rectangles have the same number of edges, but using the aspect ratio, we can find out whether the shape is a square or a rectangle.
import cv2 as cv
image = cv.imread("shape.png")
#convert image into greyscale mode
gray_image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
#find threshold of the image
_, thrash = cv.threshold(gray_image, 240, 255, cv.THRESH_BINARY)
contours, _ = cv.findContours(thrash, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
for contour in contours:
shape = cv.approxPolyDP(contour, 0.01*cv.arcLength(contour, True), True)
x_cor = shape.ravel()[0]
y_cor = shape.ravel()[1]
if len(shape) ==4:
#shape cordinates
x,y,w,h = cv.boundingRect(shape)
#width:height
aspectRatio = float(w)/h
cv.drawContours(image, [shape], 0, (0,255,0), 4)
if aspectRatio >= 0.9 and aspectRatio <=1.1:
cv.putText(image, "Square", (x_cor, y_cor), cv.FONT_HERSHEY_COMPLEX, 0.5, (0,0,0))
else:
cv.putText(image, "Rectangle", (x_cor, y_cor), cv.FONT_HERSHEY_COMPLEX, 0.5, (255,0,0))
cv.imshow("Shape", image)
cv.waitKey(0)
cv.destroyAllWindows()
Output
Behind the code
The above square and rectangle shape detection code is similar to the circle detection program. The only difference is that here we have detected the shape if it has
len(shape)==4
, and to differentiate a square from a rectangle, we have found out the width and height aspect ratio. Although for a perfect square, the aspect ratio should be 1, here we have considered some noises and treated the shape as a square if its aspect ratio lies between 0.9 to 1.1.
3) Detect Triangle and Polygon in an Image Using OpenCV in Python
Now let's detect polygon and triangle shapes in an image. The code will remain mostly the same as in the previous program. We only need to specify an
if...elif
condition, where if the shape length is 3, it would be a triangle, and if the shape length is 5, it would be a polygon.
import cv2 as cv
image = cv.imread("shape.png")
#convert image into greyscale mode
gray_image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
#find threshold of the image
_, thrash = cv.threshold(gray_image, 240, 255, cv.THRESH_BINARY)
contours, _ = cv.findContours(thrash, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)
for contour in contours:
shape = cv.approxPolyDP(contour, 0.01*cv.arcLength(contour, True), True)
x_cor = shape.ravel()[0]
y_cor = shape.ravel()[1]
#For triangle
if len(shape) ==3:
cv.drawContours(image, [shape], 0, (0,255,0), 4)
cv.putText(image, "Triangle", (x_cor, y_cor), cv.FONT_HERSHEY_COMPLEX, 0.5, (0,0,0))
#for polygon
if len(shape) ==5:
cv.drawContours(image, [shape], 0, (0,255,0), 4)
cv.putText(image, "Polygon", (x_cor, y_cor), cv.FONT_HERSHEY_COMPLEX, 0.5, (0,0,0))
cv.imshow("Shape", image)
cv.waitKey(0)
cv.destroyAllWindows()
Output
Conclusion
In this Python OpenCV tutorial, we used the
approxPolyDP()
function to find out the closed shape in an image. This method will work fine if the image, as well as all the shapes present in the image, are clear. There is another popular shape detection method called the
Hough Transform
technique present in OpenCV, but it is limited to detecting a circle. The
approxPolyDP()
technique is emerging as a better alternative when we want to detect different shapes in an image.
People are also reading:
Leave a Comment on this Post