You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于静态镜头的高效网球场边线检测及多边形拟合技术问询

基于OpenCV实现网球场外部多边形拟合

OpenCV完全支持你要的拟合需求,结合你已经用HoughLinesP实现的边线检测,我们可以通过以下步骤完成网球场外框多边形的拟合:

核心思路

  1. 分类存储有效边线:把你代码中筛选出的纵向(红色)、横向(绿色)边线单独存储,这些是构成外框的关键直线
  2. 计算有效交点:网球场外框为四边形,由纵向和横向直线相交得到四个顶点,筛选出符合球场位置逻辑的交点
  3. 多边形规整拟合:用OpenCV的approxPolyDP对交点集合进行拟合,得到平滑的外框多边形

修改后的代码实现

import math
import numpy as np
import cv2

# 计算两条线段的有效交点(仅返回线段范围内的交点)
def line_intersection(line1, line2):
    x1, y1, x2, y2 = line1
    x3, y3, x4, y4 = line2

    denom = (x1 - x2)*(y3 - y4) - (y1 - y2)*(x3 - x4)
    if denom == 0:
        return None  # 平行线段无交点
    t_num = (x1 - x3)*(y3 - y4) - (y1 - y3)*(x3 - x4)
    u_num = (x1 - x3)*(y1 - y2) - (y1 - y3)*(x1 - x2)
    t = t_num / denom
    u = -u_num / denom
    if 0 <= t <= 1 and 0 <= u <= 1:
        x = x1 + t*(x2 - x1)
        y = y1 + t*(y2 - y1)
        return (int(x), int(y))
    return None

# 加载图像
img = cv2.imread("assets/game-frames/clay-m-2012-71-870.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 100, apertureSize=3)

lines = cv2.HoughLinesP(edges, 2, np.pi/180, 100, minLineLength=20, maxLineGap=10)

vertical_lines = []  # 存储纵向边线(红色)
horizontal_lines = []  # 存储横向边线(绿色)

# 筛选并分类边线
for line in lines:
    x1, y1, x2, y2 = line[0]
    length = math.sqrt((x1 - x2)**2 + (y1 - y2)**2)
    
    if x1 == x2 or x1 < 10 or y1 < 100: 
        continue
    # 筛选纵向边线
    elif abs((y2 - y1)/(x2 - x1)) > 1.5 and abs((y2 - y1)/(x2 - x1)) < 3 and length > 200:
        vertical_lines.append((x1, y1, x2, y2))
        cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 1)
    # 筛选横向边线
    elif abs((y2 - y1)/(x2 - x1)) < 0.02 and ((x1 > 44 and x1 < 685) and (x2 < 685 and x2 > 44)) and ((y1 > 110 and y1 < 120) or (y1 > 400 and y1 < 420)):
        horizontal_lines.append((x1, y1, x2, y2))
        cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 1)
    else:
        continue 

# 计算所有纵向与横向线段的交点
intersections = []
for v_line in vertical_lines:
    for h_line in horizontal_lines:
        pt = line_intersection(v_line, h_line)
        if pt is not None:
            intersections.append(pt)

# 去重处理,避免重复交点干扰拟合
intersections = list(set(intersections))
if len(intersections) >=4:
    # 转换为OpenCV可处理的数组格式
    pts = np.array(intersections, dtype=np.int32)
    # 拟合多边形,epsilon控制拟合精度(取周长的1%)
    perimeter = cv2.arcLength(pts, True)
    approx = cv2.approxPolyDP(pts, 0.01*perimeter, True)
    # 绘制拟合后的蓝色外框多边形
    if len(approx) ==4:
        cv2.polylines(img, [approx], True, (255,0,0), 2)

cv2.imshow("Detected Lines & Court Outline", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

关键说明

  • 静态机位下,approxPolyDP的epsilon参数可以固定,保证低算力消耗
  • 交点去重处理避免了重复计算的点影响拟合结果
  • 线段交点计算逻辑只保留线段范围内的有效交点,过滤掉延长线的无效交叉

内容的提问来源于stack exchange,提问作者spazznolo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 11:36:14