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

基于OpenCV Hough变换检测车道线后无法生成车道中心线问题求助

车道中心线检测实现方案

核心原理

直接取坐标中点失效的核心原因是HoughLinesP返回的是多条离散的短线段,不是规整的左右各一条完整车道线,因此需要先对所有检测到的线段做分组拟合,得到左右两条完整的车道线,再计算中心线。
具体实现步骤:

  • 按斜率将所有线段分为左右车道线两组:图像坐标系y轴向下,左车道线斜率为负,右车道线斜率为正,同时过滤斜率绝对值过小的水平干扰线段
  • 对每组线段的斜率、截距做平均,得到左右车道线的统一线性方程y = mx + b
  • 固定车道线的纵向覆盖范围(从图像底部到感兴趣区域上边界),分别计算左右车道线在上下两个y坐标对应的x值,取两个位置的x中点作为中心线的两个端点,绘制中心线

完整修改后代码

import cv2
import numpy as np

# 边缘检测函数
def canny(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5,5), 0)
    canny = cv2.Canny(blur, 50, 150)
    return canny

# 感兴趣区域提取,顶点可根据视频分辨率自行调整
def region_of_interest(img):
    height = img.shape[0]
    width = img.shape[1]
    polygons = np.array([
        [(200, height), (width/2, height/2 + 50), (width-200, height)]
    ])
    mask = np.zeros_like(img)
    cv2.fillPoly(mask, np.int32([polygons]), 255)
    masked_img = cv2.bitwise_and(img, mask)
    return masked_img

def houghLines(cropped_canny):
    return cv2.HoughLinesP(cropped_canny, 2, np.pi/180, 100, 
        np.array([]), minLineLength=70, maxLineGap=5)

def addWeighted(frame, line_image):
    return cv2.addWeighted(frame, 0.8, line_image, 1, 1)

# 对检测到的离散线段做拟合,得到左右两条完整车道线
def average_slope_intercept(frame, lines):
    left_fit = []
    right_fit = []
    for line in lines:
        for x1, y1, x2, y2 in line:
            parameters = np.polyfit((x1, x2), (y1, y2), 1)
            slope = parameters[0]
            intercept = parameters[1]
            # 过滤斜率异常的干扰线段,阈值可根据实际场景调整
            if slope < -0.5: 
                left_fit.append((slope, intercept))
            elif slope > 0.5: 
                right_fit.append((slope, intercept))
    left_fit_avg = np.average(left_fit, axis=0) if len(left_fit) > 0 else None
    right_fit_avg = np.average(right_fit, axis=0) if len(right_fit) > 0 else None
    
    # 将线性方程参数转换为线段端点坐标
    def make_coordinates(img, line_params):
        slope, intercept = line_params
        y1 = img.shape[0]
        y2 = int(y1 * 0.6) # 车道线上边界,和ROI范围对齐即可
        x1 = int((y1 - intercept)/slope)
        x2 = int((y2 - intercept)/slope)
        return np.array([x1, y1, x2, y2])
    
    left_line = make_coordinates(frame, left_fit_avg) if left_fit_avg is not None else None
    right_line = make_coordinates(frame, right_fit_avg) if right_fit_avg is not None else None
    return np.array([left_line, right_line]) if left_line is not None and right_line is not None else None

def display_lines(img, lines, center_line=None):
    line_image = np.zeros_like(img)
    # 绘制红色左右车道线
    if lines is not None:
        for x1, y1, x2, y2 in lines:
            cv2.line(line_image,(x1,y1),(x2,y2),(0,0,255),5)
    # 绘制绿色中心线,颜色粗细可自行调整
    if center_line is not None:
        cx1, cy1, cx2, cy2 = center_line
        cv2.line(line_image, (cx1, cy1), (cx2, cy2), (0,255,0), 5)
    return line_image

cap = cv2.VideoCapture("videoplayback (online-video-cutter.com) (1).mp4")
while(cap.isOpened()):
    ret, frame = cap.read()
    if not ret:
        break
    canny_image = canny(frame)
    cropped_canny = region_of_interest(canny_image)

    lines = houghLines(cropped_canny)
    averaged_lines = average_slope_intercept(frame, lines)
    center_line = None
    if averaged_lines is not None:
        left_line, right_line = averaged_lines
        # 计算中心线两个端点
        cx1 = (left_line[0] + right_line[0]) // 2
        cy1 = left_line[1]
        cx2 = (left_line[2] + right_line[2]) // 2
        cy2 = left_line[3]
        center_line = np.array([cx1, cy1, cx2, cy2])
    
    line_image = display_lines(frame, averaged_lines, center_line)
    combo_image = addWeighted(frame, line_image)
    
    cv2.imshow("result", combo_image)
    
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

调整说明

如果适配你的视频场景出现偏差,可调整以下参数:

  • 斜率过滤阈值-0.5、0.5,适配不同拍摄角度的车道线倾斜程度
  • 感兴趣区域的多边形顶点、车道线上边界系数0.6,和实际画面中车道的覆盖范围对齐

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 17:24:02