4. 车道线检测

任务目标

本案例使用OpenCV传统图像处理管线,从单张道路测试图像中提取车道线。核心步骤为:图像灰度化→高斯模糊降噪→Canny边缘检测→感兴趣区域(ROI)掩膜→霍夫变换直线检测→在原图上叠加绘制检测结果。最终输出一张可视化图像,车道线以彩色线段标注。

环境依赖

需要Python 3.8+、OpenCV(opencv-python)、NumPy。测试图像使用OpenCV内置的test.jpg(位于opencv安装目录的samples/data下),也可替换为任意道路图像。

关键完整代码

import cv2
import numpy as np

def region_of_interest(img, vertices):
    """应用ROI掩膜,只保留多边形区域内的像素"""
    mask = np.zeros_like(img)
    cv2.fillPoly(mask, [vertices], 255)
    return cv2.bitwise_and(img, mask)

def draw_lane_lines(img, lines):
    """在图像副本上绘制检测到的车道线"""
    line_img = np.zeros_like(img)
    if lines is not None:
        for line in lines:
            x1, y1, x2, y2 = line[0]
            cv2.line(line_img, (x1, y1), (x2, y2), (0, 0, 255), 8)
    return cv2.addWeighted(img, 0.8, line_img, 1.0, 0.0)

# 1. 读取图像
img = cv2.imread('test.jpg')
if img is None:
    raise FileNotFoundError("未找到test.jpg,请检查路径或替换为自定义道路图像")
img = cv2.resize(img, (960, 540))  # 统一尺寸便于参数调试
height, width = img.shape[:2]

# 2. 灰度化 + 高斯模糊
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)

# 3. Canny边缘检测
edges = cv2.Canny(blur, 50, 150)

# 4. 定义梯形ROI(针对前方道路区域)
vertices = np.array([[(0, height),
                      (width * 0.45, height * 0.6),
                      (width * 0.55, height * 0.6),
                      (width, height)]], dtype=np.int32)
roi_edges = region_of_interest(edges, vertices)

# 5. 霍夫变换检测直线
lines = cv2.HoughLinesP(roi_edges, rho=1, theta=np.pi/180,
                        threshold=50, minLineLength=40, maxLineGap=100)

# 6. 在原图上绘制并保存结果
result = draw_lane_lines(img, lines)
cv2.imwrite('lane_detection_result.jpg', result)
print("检测到直线数量:", 0 if lines is None else len(lines))
print("结果已保存为 lane_detection_result.jpg")

运行与验证

  1. 将上述代码保存为lane_detection.py,确保test.jpg与脚本在同一目录(或修改路径)。
  2. 终端运行:python lane_detection.py
  3. 验证通过条件:程序无报错退出,输出检测到的直线数量(通常为4~10条),并生成lane_detection_result.jpg。打开结果图,应看到左右车道线被红色线段清晰标注,且标注位置与图像中实际车道线基本吻合。

参数调优说明

若检测效果不佳,优先调整以下参数:

  • Canny阈值:Canny(blur, 50, 150)中降低阈值可检测更多边缘,升高则减少噪声边缘。
  • ROI顶点:梯形区域需覆盖图像下半部分的车道延伸方向,若车道弯曲或视角不同,需修改vertices坐标。
  • 霍夫参数:threshold(累加器阈值)越高要求直线越明显;minLineLength过滤短线段;maxLineGap控制同一直线上断点合并间距。

常见问题

  • 检测到大量杂乱短线:多为Canny低阈值或ROI过大引入路边噪声,可提高Canny阈值或收窄ROI。
  • 车道线断裂不连续:增大maxLineGap或降低minLineLength,使断线合并为长线段。
  • 输出图像全黑:检查ROI顶点坐标是否超出图像边界,或cv2.imread路径错误导致图像未正确加载。
原图 + ROI区域(绿色) 红色线段 = 霍夫变换检测结果 地平线

上图展示了处理流程中各阶段的空间关系:绿色半透明区域为ROI掩膜范围,红色线段为最终检测并绘制的车道线。实际运行时可通过调整ROI顶点和霍夫参数,使红色线段与白色车道标记对齐。