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

美式足球场完整标线检测及单应性变换场域校正技术问询

美式足球场标线检测与鸟瞰视角变换问题

问题背景

我正尝试检测美式足球场的完整标线,实现球员定位并通过**单应性变换(homography)**将场域转换为鸟瞰视角。目前使用Python与OpenCV开发,但无法获取全场完整标线。

输入图像

Input image

当前检测结果

参考相关方案后,仅得到如下结果:
Extended lines on field
当前结果已接近目标,但希望每条水平标线都能以单条蓝色线条贯穿全场。

现有处理流程

  • 掩码提取场地白色区域
  • 使用Canny边缘检测:
    canny = cv2.Canny(img_mask, 50, 150, apertureSize=3)
    
    Canny image detection
  • 从Canny结果中提取霍夫线:
    lines_p = cv2.HoughLinesP(canny, 1, np.pi / 180, 100, None, 0, 20)
    
    Hough line detection
  • 延伸并合并相近线条得到上述结果

相关代码

def extend_lines(lines, extension_length=20):
    """
    Extend short line segments by a specified length.

    Parameters:
    - lines: List of line segments in the format ((x1, y1), (x2, y2)).
    - extension_length: Length by which to extend the lines.

    Returns:
    - List of extended line segments.
    """
    extended_lines = []

    for line in lines:
        print(line)
        x1, y1, x2, y2 = line[0]

        # Calculate the vector representing the line segment
        dx, dy = x2 - x1, y2 - y1

        # Normalize the vector
        length = np.sqrt(dx**2 + dy**2)
        if length > 0:
            dx /= length
            dy /= length

            # Extend the line segment by the specified length
            x1_extended = int(x1 - extension_length * dx)
            y1_extended = int(y1 - extension_length * dy)
            x2_extended = int(x2 + extension_length * dx)
            y2_extended = int(y2 + extension_length * dy)

            extended_lines.append([[x1_extended, y1_extended, x2_extended, y2_extended]])
        else:
            extended_lines.append(line)
    for i in reversed(range(len(extended_lines))):
        line = extended_lines[i]
        print(line[0])
        length = np.sqrt((line[0][2] - line[0][0])**2 + (line[0][3] - line[0][1])**2)
        if length < 150:
            del extended_lines[i]


    return extended_lines

def merge_close_lines(lines, epsilon=50, min_samples=2):
    """
    Merge lines that are close to each other.

    Parameters:
    - lines: List of line segments in the format ((x1, y1), (x2, y2)).
    - epsilon: Maximum distance to consider for merging lines.
    - min_samples: Minimum number of samples required to form a cluster.

    Returns:
    - List of merged line segments.
    """
    points = np.array([[(line[0][0] + line[0][2]) / 2, (line[0][1] + line[0][3]) / 2] for line in lines])

    # Apply DBSCAN clustering
    db = DBSCAN(eps=epsilon, min_samples=min_samples).fit(points)
    labels = db.labels_

    # Group lines by cluster label
    grouped_lines = {}
    for i, label in enumerate(labels):
        if label in grouped_lines:
            grouped_lines[label].append(lines[i])
        else:
            grouped_lines[label] = [lines[i]]

    # Fit a line to each cluster
    merged_lines = []
    for label, lines_in_cluster in grouped_lines.items():
        merged_line = find_longest_line(lines_in_cluster)
        merged_lines.append(merged_line)

    return merged_lines

def find_longest_line(lines):
    longest_line = None
    max_length = 0

    for line in lines:
        x1, y1, x2, y2 = line[0]
        length = np.sqrt((x2 - x1)**2 + (y2 - y1)**2)

        if length > max_length:
            max_length = length
            longest_line = line

    return longest_line

需求

寻求更稳定准确的标线检测方案,或基于现有结果实现场域变换的方法。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 17:07:53