Catalanforyouforever
Catalanforyouforever

Reputation: 33

Hough Transform for Line and Circle Detection of a pool table. Lines and corners of the pool table, Pool Balls

So I was trying to detect the lines, corners and circles(pool balls) from this image. enter image description here

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. enter image description here 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

Answers (0)

Related Questions