Detect semicircle in OpenCV
Categories:
Detecting Semicircles in OpenCV: A Comprehensive Guide

Learn how to effectively detect semicircular shapes in images using OpenCV, leveraging techniques like edge detection, Hough Transform, and contour analysis.
Detecting specific geometric shapes like semicircles in images is a common task in computer vision, with applications ranging from industrial inspection to autonomous navigation. Unlike full circles, semicircles present a unique challenge due to their open-ended nature and the need to identify both the curved arc and the connecting line segment (diameter). This article will guide you through a robust approach using OpenCV, combining edge detection, Hough Transform for lines, and contour analysis to accurately identify semicircles.
Understanding the Challenge of Semicircle Detection
Semicircles are essentially half-circles, characterized by a curved arc and a straight line segment forming its diameter. The primary difficulty in detecting them lies in distinguishing them from full circles, other curved shapes, or even just random arcs. Traditional circle detection methods like the Hough Circle Transform are optimized for complete circles and may struggle with partial arcs. Therefore, a multi-stage approach is often required, breaking down the problem into detecting the arc and then verifying the presence of its diameter.
flowchart TD A[Input Image] --> B{Pre-processing: Grayscale, Blur} B --> C[Edge Detection: Canny] C --> D{Hough Line Transform} C --> E{Contour Detection} D --> F{Filter Lines: Length, Orientation} E --> G{Filter Contours: Arc Length, Area} F & G --> H{Combine & Verify: Arc-Line Proximity, Angle} H --> I[Detected Semicircles]
High-level workflow for semicircle detection in OpenCV.
Step-by-Step Detection Methodology
Our approach involves several key steps to isolate and identify semicircles. We'll start with image pre-processing, move to edge detection, then use the Hough Line Transform to find potential diameters, and finally, analyze contours to find the curved arcs. The crucial part is then combining these findings to confirm a semicircle.
1. 1. Pre-processing and Edge Detection
Convert the input image to grayscale and apply a Gaussian blur to reduce noise. Then, use the Canny edge detector to find prominent edges. These edges will form the basis for both line and arc detection.
2. 2. Hough Line Transform for Diameter Detection
Apply the Probabilistic Hough Line Transform (cv2.HoughLinesP
) on the Canny edge map. This will detect straight line segments. Filter these lines based on length and orientation to identify potential diameters of semicircles. A diameter should be a relatively long, straight line.
3. 3. Contour Detection for Arc Identification
Find contours in the Canny edge map using cv2.findContours
. Iterate through these contours and filter them based on properties like arc length and area. We are looking for contours that resemble arcs, so they should have a certain curvature and not be too small or too large.
4. 4. Combining Lines and Arcs to Form Semicircles
This is the most critical step. For each potential arc contour, try to find a corresponding line segment (diameter) from the Hough lines. A valid pair would have the endpoints of the line segment lying close to the endpoints of the arc, and the line segment should roughly bisect the arc. You might also check the angle between the line and the tangents at the arc's endpoints.
import cv2
import numpy as np
def detect_semicircles(image_path):
img = cv2.imread(image_path)
if img is None:
print("Error: Could not load image.")
return
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150, apertureSize=3)
# 1. Hough Line Transform for potential diameters
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=50, minLineLength=50, maxLineGap=10)
# 2. Contour Detection for potential arcs
contours, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
detected_semicircles = []
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
line_center = np.array([(x1 + x2) / 2, (y1 + y2) / 2])
line_length = np.sqrt((x2 - x1)**2 + (y2 - y1)**2)
if line_length < 50: # Filter out very short lines
continue
for contour in contours:
# Approximate contour to simplify and check for arc-like shape
perimeter = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.02 * perimeter, True)
# Filter contours that are too small or too large, or not arc-like
if len(approx) < 5 or len(approx) > 50: # Heuristic for arc-like shapes
continue
# Check if the arc's endpoints are close to the line's endpoints
# This is a simplified check; a more robust approach would involve geometry
# For demonstration, we'll check if the line's center is near the arc's 'center'
M = cv2.moments(contour)
if M["m00"] == 0: continue
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
arc_center = np.array([cx, cy])
distance = np.linalg.norm(line_center - arc_center)
# A more robust check would involve:
# 1. Finding the two furthest points on the arc (potential endpoints)
# 2. Checking if these points are close to (x1,y1) and (x2,y2)
# 3. Verifying the arc's curvature and orientation relative to the line
# Simple distance check for demonstration
if distance < line_length / 2: # If arc center is close to line center
# Further checks needed: arc orientation, endpoints alignment
detected_semicircles.append((line, contour))
# Draw for visualization
cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.drawContours(img, [contour], -1, (0, 0, 255), 2)
cv2.imshow("Detected Semicircles", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Example usage:
detect_semicircles("path/to/your/image.jpg")
Python code demonstrating the basic structure for semicircle detection.
detect_semicircles
function provided is a basic framework. For real-world applications, the 'Combining Lines and Arcs' step requires significant geometric analysis. You'll need to calculate the distance between arc endpoints and line endpoints, check the angle between the line and the arc's tangent at its ends, and ensure the arc's curvature is consistent with a semicircle.Refining Semicircle Verification
The most challenging aspect is accurately verifying that a detected arc and a detected line segment indeed form a semicircle. This involves several geometric checks:
- Endpoint Proximity: The two endpoints of the detected arc should be very close to the two endpoints of the detected line segment.
- Midpoint Alignment: The midpoint of the line segment should be close to the center of the circle from which the arc originates.
- Radius Consistency: The distance from the line's midpoint to any point on the arc should be approximately constant (the radius).
- Arc Length: The arc length should be roughly half the circumference of a circle with the detected radius.
- Orientation: The line segment should be perpendicular to the radius connecting the circle's center to the arc's midpoint.

Key geometric properties for verifying a semicircle.
cv2.HoughCircles
is generally not suitable for detecting semicircles because it's designed to find complete circular shapes. While it might detect a full circle if a semicircle is part of a larger, faint circle, it won't reliably identify the semicircle itself as a distinct entity.Implementing these geometric checks requires careful calculation of distances, angles, and potentially fitting a circle to the arc points to determine its center and radius. This iterative refinement process is key to achieving high accuracy in semicircle detection.