How to Detect Rectangle in Python OpenCV
-
Use the
findContours()
andcontourArea()
Function of OpenCV to Detect Rectangles in Images in Python - Use the Hough Transform of OpenCV to Detect Rectangles in Images in Python
- Conclusion
OpenCV, short for Open Source Computer Vision Library, is a powerful toolkit that provides a wide range of functions for image manipulation and graphical analysis. This common task in computer vision involves techniques that not only process images but also identify shapes within them.
This tutorial will discuss detecting rectangles using the findContours()
and contourArea()
, and HoughLinesP()
functions of OpenCV
in Python. This process, essential in object detection, involves several steps, each crucial for accurately identifying rectangles in various types of images.
Use the findContours()
and contourArea()
Function of OpenCV to Detect Rectangles in Images in Python
We can detect a rectangle present in an image using the findContours()
function of OpenCV, and we can use the contourArea()
function to sort different rectangles according to their area.
Understanding findContours()
and contourArea()
findContours()
: This function retrieves all the contours from the binary image.
contourArea()
: Calculates the area of the contour, which is used to filter out the contours that do not correspond to rectangles.
Key Functions and Parameters
cv2.findContours(image, mode, method)
: Finds contours in a binary image.
image
: Source, an 8-bit single-channel image. Non-zero pixels are treated as 1’s.mode
: Contour retrieval mode (e.g.,cv2.RETR_TREE
,cv2.RETR_EXTERNAL
).method
: Contour approximation method (e.g.,cv2.CHAIN_APPROX_SIMPLE
,cv2.CHAIN_APPROX_NONE
).
cv2.contourArea(contour)
: Computes the area of the contour.
contour
: The contour input.
We can find the contours of the given image using the findContours()
function of OpenCV, but we have to use a binary or black and white image inside the findContours()
function.
To convert the given image into binary, we have to use the cvtColor()
and threshold()
function of OpenCV
. The cvtColor()
function is used to convert 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
. See the Python code below, where we use a test image named rectangle.png
.
import cv2
import numpy as np
# Read the input image
input_image = cv2.imread("rectangle.png")
original_image = input_image.copy()
# Convert image to grayscale
grayscale_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY)
# Convert to binary image
_, binary_image = cv2.threshold(grayscale_image, 150, 255, cv2.THRESH_BINARY)
# Find all the contours
all_contours, hierarchy = cv2.findContours(
binary_image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE
)
# Loop through individual contours
for contour in all_contours:
# Approximate contour to a polygon
perimeter = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.02 * perimeter, True)
# Calculate aspect ratio and bounding box
if len(approx) == 4:
x, y, w, h = cv2.boundingRect(approx)
aspect_ratio = float(w) / h
# Draw bounding box
cv2.drawContours(original_image, [approx], -1, (0, 255, 0), 3)
cv2.putText(
original_image,
"Rectangle",
(x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
(0, 255, 0),
2,
)
# Display the result
cv2.imshow("Detected Rectangles", original_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
Output:
First, we convert the input image to grayscale and then apply thresholding to obtain a binary image. This step is critical for our contour detection process.
Using the findContours()
function, we extract the contours from this binary image. In this phase, we employ cv2.RETR_EXTERNAL
to retrieve only the extreme outer contours and cv2.CHAIN_APPROX_SIMPLE
to remove redundant points, effectively compressing the contour for efficiency.
As we analyze each contour, the contourArea()
function becomes instrumental in filtering out the smaller, less significant contours. Our focus is on the contours of a certain size that are more likely to be relevant to our task.
Next, we use the cv2.approxPolyDP()
function to approximate the shape of individual contour to a polygon. This is a pivotal moment in our process: if a polygon has four vertices, we infer that it’s probably a rectangle, thus confirming the detected shape.
Finally, after identifying these rectangles, we draw them onto the original image. By marking these rectangles on the original image, we can clearly see the results of our collaborative efforts in image processing.
Use the Hough Transform of OpenCV to Detect Rectangles in Images in Python
The Hough Transform stands as a widely employed technique in image processing to detect shapes, particularly simple ones such as lines, circles, and rectangles. When implemented in OpenCV, this method proves notably effective in identifying straight edges, and consequently, it excels in detecting rectangles within images.
Understanding the Hough Transform
The Hough Transform algorithm works by transforming each point in the image to a sinusoidal curve in the parameter space. The intersection of these curves indicates the presence of a line.
For rectangle detection, identifying four lines that form a closed quadrilateral is key.
The cv2.HoughLinesP
function is utilized to detect lines in the binary image. These lines essentially represent the boundary points of potential rectangles in the image.
Key Functions and Parameters
cv2.HoughLinesP(image, rho, theta, threshold)
: Detects lines in an image.
image
: The output of an edge detector (like a binary image).rho
: The resolution of the accumulator in pixels.theta
: The resolution of the accumulator in radians.threshold
: The minimum number of intersections to detect a line.
import cv2
import numpy as np
def detect_rectangles(image_path):
image = cv2.imread(image_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150, apertureSize=3)
# Debug: Show the result of edge detection
cv2.imshow("Edges", edges)
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 80, minLineLength=50, maxLineGap=20)
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imshow("Rectangles Detected", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
detect_rectangles("rectangle.png")
In our image processing workflow, we begin by reading the image and converting it to grayscale, a crucial step to simplify subsequent edge detection. Employing the cv2.Canny()
function, we identify significant edges, laying the foundation for precise line detection.
We then turn to cv2.HoughLinesP()
for its crucial role in pinpointing lines within the image. We recognize that the accuracy of our line detection hinges significantly on how we fine-tune parameters like rho
, theta
, threshold
, minLineLength
, and maxLineGap
.
By carefully adjusting these parameters, we aim to enhance the precision of our line detection process.
Output:
Conclusion
We delved into two primary methodologies: the use of findContours()
and contourArea()
for contour-based rectangle detection and the application of the Hough Transform for identifying geometric shapes. Throughout this guide, we have emphasized the significance of fine-tuning parameters and adapting techniques to suit specific image characteristics.
Our practical examples and detailed explanations aimed to provide a comprehensive understanding of these methods, showcasing the versatility and robustness of OpenCV.