Reputation: 33
So I was trying to detect the lines, corners and circles(pool balls) from this image.
import cv2
import numpy as np
import matplotlib.pyplot as plt
# Load the image
image = cv2.imread("figure1-assignment3.jpg")
original_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# Define region of interest (ROI) to focus on the bottom two-thirds of the image
height, width = image.shape[:2]
roi = image[int(height * 1/3):, :]
roi_gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
# Apply edge detection
edges = cv2.Canny(roi_gray, 50, 150, apertureSize=3)
# Hough Line Transform
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=50, minLineLength=100, maxLineGap=10)
# Draw detected lines on the original image
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(roi, (x1, y1), (x2, y2), (255, 0, 0), 2)
# Find intersections of the lines to detect corners
if lines is not None:
for i in range(len(lines)):
for j in range(i+1, len(lines)):
line1 = lines[i][0]
line2 = lines[j][0]
x1, y1 = line1[0], line1[1]
x2, y2 = line1[2], line1[3]
x3, y3 = line2[0], line2[1]
x4, y4 = line2[2], line2[3]
denom = ((x1 - x2) * (y3 - y4)) - ((y1 - y2) * (x3 - x4))
if denom != 0:
x = int((((x1 * y2) - (y1 * x2)) * (x3 - x4) - ((x1 - x2) * (x3 * y4 - y3 * x4))) / denom)
y = int((((x1 * y2) - (y1 * x2)) * (y3 - y4) - ((y1 - y2) * (x3 * y4 - y3 * x4))) / denom)
if 0 <= x < width and 0 <= y < height:
cv2.circle(roi, (x, y), 5, (0, 0, 255), -1)
# Hough Circle Transform
circles = cv2.HoughCircles(roi_gray, cv2.HOUGH_GRADIENT, dp=1, minDist=30, param1=150, param2=20, minRadius=10, maxRadius=30)
if circles is not None:
circles = np.round(circles[0, :]).astype("int")
for (x, y, r) in circles:
cv2.circle(roi, (x, y), r, (0, 255, 0), 4)
# Find contours and approximate polygons
contours, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:5]
# Find the corners of the pool table
for contour in contours:
peri = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.02 * peri, True)
if len(approx) == 4:
for point in approx:
x, y = point[0]
cv2.circle(roi, (x, y), 5, (0, 0, 255), -1)
break
# Display the result using matplotlib
fig, axes = plt.subplots(1, 2, figsize=(14, 7))
axes[0].imshow(original_image)
axes[0].set_title("Original Image")
axes[0].axis('off')
axes[1].imshow(cv2.cvtColor(roi, cv2.COLOR_BGR2RGB))
axes[1].set_title("Detected Lines, Balls, and Corners")
axes[1].axis('off')
plt.show()
And this is the best result I could produce from this code.
What I tried was : first detect the correct border lines,
Then the intersection of the border lines are the corners
And circles are dealt separately.
Now I have produced too many corners. Too few lines.
Also someone gave me this advice: Trick is to identify the lines you want first. It's trial and error to pick the correct ones. But you can reduce the number of lines based on the parameters. Then for those selected lines, you find the intersection For the corners.
I have tried several different parameters so far, nothing came of those. Also, Am I overthinking the line detection? Should it be simpler? I don't know guys. I feel as thought I am very close.
Upvotes: 0
Views: 70