Shape detection is a technique used in image processing and computer vision, that enables us to identify and classify various shapes present within an image. By analyzing the geometric attributes of objects, shape detection forms the basis for numerous applications, including object recognition, industrial automation, and quality assessment.
Here are the steps to detect shapes in your image:
First of all, we need to install OpenCV. We can install it using the following command:
pip install opencv-python
After installing OpenCV, we will start by importing the necessary libraries:
import cv2import numpy as np
We import the cv2
for image processing and manipulation and the numpy
for array operations.
Next, we need to load the image and preprocess it for better detection. We will convert the image to grayscale and apply Gaussian Blur to reduce noise in the image. Here is a sample code:
image = cv2.imread('image.png')gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)blur = cv2.GaussianBlur(gray, (5, 5), 0)
We load an image using the cv2.imread()
and convert it to grayscale using the cv2.cvtColor()
. Then we apply Gaussian blur using the cv2.GaussianBlur()
. Following is the image that we will be using:
In this step, we will use the Canny edge detection algorithm to detect the edges within the grayscale image. Edge detection highlights the significant transitions in pixel intensity, which often correspond to object boundaries. Here is the usage of the Canny edge detection function:
edges = cv2.Canny(blur, threshold1, threshold2)
We can adjust the threshold1
and threshold2
parameters to control the sensitivity of edge detection.
Apply the cv2.findContours()
function to identify contours in the edge-detected image. The function returns a list of contours and hierarchy information. Here is the syntax:
contours, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
We use the _
variable to discard hierarchy data. You can also adjust the second argument (cv2.RETR_EXTERNAL
) to specify the contour retrieval mode.
To simplify the representation of contours while preserving their core structure, we employ the cv2.approxPolyDP()
function. By iteratively approximating the contours, we reduce the number of vertices while retaining the underlying shape’s integrity. These approximated contours will serve as a foundation for subsequent shape classification.
for contour in contours:epsilon = 0.04 * cv2.arcLength(contour, True)approx = cv2.approxPolyDP(contour, epsilon, True)cv2.drawContours(image, [approx], 0, (0, 255, 0), 2)
This step involves classifying the shapes based on the number of vertices present in the approximated contours. By analyzing the vertex count, we categorize the shapes into various geometric forms, such as triangles, squares, rectangles, pentagons, and circles. The identified shape names are then superimposed onto the original image using the cv2.putText()
function.
for contour in contours:epsilon = 0.04 * cv2.arcLength(contour, True)approx = cv2.approxPolyDP(contour, epsilon, True)vertices = len(approx)if vertices == 3:shape = "Triangle"elif vertices == 4:(x, y, w, h) = cv2.boundingRect(approx)ar = w / float(h)# A square will have an aspect ratio(ar) that is approximately# equal to one, otherwise, the shape is a rectangleshape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"elif vertices == 5:shape = "Pentagon"else:shape = "Circle"cv2.putText(image, shape, (approx[0][0][0], approx[0][0][1]+5), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
Use the cv2.imshow()
to display the original image and the contour image.
cv2.imshow('Shape Detection', image)cv2.waitKey(0)cv2.destroyAllWindows()
The cv2.waitKey(0)
function waits for a key press before closing windows, and the cv2.destroyAllWindows()
closes all windows.
By following these steps, the complete code will turn out like this:
import cv2import numpy as np# Load and preprocess an Imageimage = cv2.imread('image.png')gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)blur = cv2.GaussianBlur(gray, (5, 5), 0)# Perform edge detectionedges = cv2.Canny(blur, 30, 150)# Find contourscontours, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# Classifying shapesfor contour in contours:epsilon = 0.04 * cv2.arcLength(contour, True)approx = cv2.approxPolyDP(contour, epsilon, True)vertices = len(approx)if vertices == 3:shape = "Triangle"elif vertices == 4:(x, y, w, h) = cv2.boundingRect(approx)ar = w / float(h)shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"elif vertices == 5:shape = "Pentagon"else:shape = "Circle"cv2.drawContours(image, [approx], 0, (0, 255, 0), 2)cv2.putText(image, shape, (approx[0][0][0], approx[0][0][1]+5), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)# Save Resultscv2.imwrite('output/DetectedShapes.png',image)
Shape detection is a technique in computer vision that plays a crucial role in various image analysis tasks. OpenCV simplifies the process by offering tools for shape detection. Furthermore, you can explore more advanced techniques and combine shape detection with machine learning to achieve even more sophisticated results in your projects.
Free Resources