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")
运行与验证
- 将上述代码保存为
lane_detection.py,确保test.jpg与脚本在同一目录(或修改路径)。 - 终端运行:
python lane_detection.py - 验证通过条件:程序无报错退出,输出检测到的直线数量(通常为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顶点和霍夫参数,使红色线段与白色车道标记对齐。