如何用OpenCV获取角点(x,y)坐标及不同背景下台球桌定位
问题解答
1. 用OpenCV查找角点(x, y)坐标
OpenCV提供了多种成熟的角点检测方案,常用的有Harris角点检测和Shi-Tomasi角点检测,具体实现如下:
Harris角点检测
import cv2 as cv import numpy as np img = cv.imread("your_image.png") gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) gray = np.float32(gray) # 执行Harris角点检测 dst = cv.cornerHarris(gray, 2, 3, 0.04) # 膨胀结果便于标记角点 dst = cv.dilate(dst, None) # 阈值化筛选角点 threshold = 0.01 * dst.max() corners = np.where(dst > threshold) # 转换为(x,y)坐标格式 corner_coords = [(x, y) for y, x in zip(corners[0], corners[1])] # 可视化角点 img[dst > threshold] = [0, 0, 255] cv.imshow("Harris Corners", img) cv.waitKey(0) cv.destroyAllWindows()
Shi-Tomasi角点检测(稳定性更强)
import cv2 as cv import numpy as np img = cv.imread("your_image.png") gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 检测指定数量的最强角点 corners = cv.goodFeaturesToTrack(gray, maxCorners=100, qualityLevel=0.01, minDistance=10) corners = np.int0(corners) # 提取(x,y)坐标 corner_coords = [(corner[0][0], corner[0][1]) for corner in corners] # 可视化角点 for corner in corners: x, y = corner.ravel() cv.circle(img, (x, y), 3, (0, 255, 0), -1) cv.imshow("Shi-Tomasi Corners", img) cv.waitKey(0) cv.destroyAllWindows()
2. 提取台球桌轮廓及球袋坐标
针对背景存在差异的台球桌图像,可通过预处理+边缘检测+直线拟合+交点计算的流程提取桌台轮廓,再基于轮廓定位球袋(标准台球桌共6个球袋:4个角点+2个侧边中点),优化后的代码如下:
import cv2 as cv import numpy as np def get_table_corners(lines): # 分类直线为水平/垂直方向 horizontal_lines = [] vertical_lines = [] for line in lines: x1, y1, x2, y2 = line[0] # 通过斜率区分水平/垂直线 if abs(y2 - y1) < abs(x2 - x1): horizontal_lines.append((y1 + y2) / 2) else: vertical_lines.append((x1 + x2) / 2) # 筛选最外沿的水平/垂直直线 horizontal_lines = sorted(horizontal_lines) vertical_lines = sorted(vertical_lines) top_y, bottom_y = horizontal_lines[0], horizontal_lines[-1] left_x, right_x = vertical_lines[0], vertical_lines[-1] # 返回四个角点坐标 return [(left_x, top_y), (right_x, top_y), (right_x, bottom_y), (left_x, bottom_y)] # 读取图像 img = cv.imread(cv.samples.findFile('1.png')) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 预处理:高斯模糊降低噪声干扰 blurred = cv.GaussianBlur(gray, (5, 5), 0) # Canny边缘检测 edges = cv.Canny(blurred, 50, 150, apertureSize=3) # 霍夫直线检测,调整参数适配台球桌线条 lines = cv.HoughLinesP(edges, 1, np.pi/180, threshold=80, minLineLength=100, maxLineGap=20) if lines is not None: # 获取台球桌四个角点 table_corners = get_table_corners(lines) # 绘制橙色桌台轮廓(匹配示例样式) for i in range(4): cv.line(img, (int(table_corners[i][0]), int(table_corners[i][1])), (int(table_corners[(i+1)%4][0]), int(table_corners[(i+1)%4][1])), (0, 165, 255), 3) # 提取6个球袋坐标 pocket_coords = table_corners.copy() # 添加上下侧边中点 pocket_coords.append(((left_x + right_x)/2, top_y)) pocket_coords.append(((left_x + right_x)/2, bottom_y)) # 标记球袋位置 for (x, y) in pocket_coords: cv.circle(img, (int(x), int(y)), 5, (0, 0, 255), -1) cv.imshow('台球桌轮廓与球袋', img) cv.waitKey(0) cv.destroyAllWindows()
关键优化说明
- 新增高斯模糊预处理,过滤背景噪声对边缘检测的干扰
- 调整霍夫直线检测参数,提升桌台线条的识别精度
- 加入直线分类逻辑,精准筛选桌台最外沿的四条边,计算得到准确角点
- 基于标准台球桌结构直接推导球袋坐标,无需额外检测
内容的提问来源于stack exchange,提问作者Mojtaba
相关产品推荐
相关产品推荐

