首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于传统方法的车道线检测

基于传统方法的车道线检测

作者头像
小飞侠xp
发布2020-03-20 18:03:05
1K0
发布2020-03-20 18:03:05
举报

1.canny边缘检测

基本原理:检测亮度的急剧变化(大梯度 比如从白色到黑色)在给定阈值下定义为边

预处理:转换灰度图

Canny:
  • 降噪:噪声容易导致误检,用 5*5 的高斯滤波器(正太分布核)对图像做卷积(平滑图像) [Canny自带]
  • 求亮度梯度:在平滑的图像上用 Sobel/Roberts/Prewitt 核沿 x 轴和 y 轴检测边缘是水平/垂直/对角线
  • 非极大值抑制:细化边缘。检查每个像素值在先前计算的梯度方向上是否为局部最大值(相比B,C如果A是局部最大则在下一个点上检查非极大值抑制否则将 A 的像素值设置为 0 并抑制A
  • hysteresis thresholding:非极大值抑制后可以确认强像素在最终边缘映射中。但还要对弱像素进行进一步分析确定它是边缘还是噪声。 a) 梯度> maxVal 的是边缘 b) < minVal 的不是边缘并将其删除 c) 梯度在[minVal, maxVal] 的像素只有在和梯度高于 maxVal 的像素相连时才是边缘
def do_canny(frame):
    gray = cv.cvtColor(frame, cv.COLOR_RGB2GRAY)
    blur = cv.GaussianBlur(gray, (5,5),0)
    canny = cv.Canny(blur,50,150)
    return canny

2.手动分割路面区域、

手动指定一个三角形来分割出路面区域,去除其他干扰边缘

def do_segment(frame):
    height = frame.shape[0]
    polygons = np.array([
    [(0,height), (800,height),(380,290)]
    ])//对应三个点
    mask = np.zeros_like(frame)//生成一张图片,只不过所有值都是0
    cv.fillPoly(mask, polygons, 255) //将三个点围城区域填充为255,其余还是0 ,实际就是掩码
    segment = cv.bitwise_and(frame,mask)//比特位的与操作 255实际就是8比特位为1然后与原像素进行比特位的与操作,就会保留原来像素的值
    return segment

3.霍夫变换得到车道线

hough = cv.HoughLinesP(segment, 2, np.pi / 180,100, np.array([]), minLineLength = 100, maxLineGap = 50)

霍夫变换如何帮助我们找到线?

  • 将笛卡尔坐标系中一系列可能被连成线的点 -> 该点在霍夫空间中对应的线
  • 找到霍夫空间中的交点(m,b)就是那条线的方程
  • 特殊情况:线垂直时梯度无穷大,无法在霍夫空间中表示出来。为了解决这个问题,我们在笛卡尔坐标系中用极坐标法表示直线。对应到霍夫空间也做对应变化。
  • 霍夫空间中相交的曲线越多,交点表示的线在笛卡尔坐标系对应的点越多。我们在霍夫空间中定义交点的最小阈值来检测线。霍夫变换跟踪了帧中的每个点的霍夫空间交点。如果交点数量超过了阈值就确定一条对应参数 θ 和 d的线。

4.获取车道线并叠加到原始图像中

综合所有线,求得两条车道线的平均斜率和截距

def calculate_line(frame, lines):
    left = []
    right = []
    for line in lines:
        x1,y1,x2,y2 = line.reshape(4) # reshape line from 2d to 1d
        parameters = np.polyfit((x1,x2),(y1,y2),1) # 拟合一条直线返回系数
        slope = parameters[0] #斜率
        y_intercept = parameters[1]
        if slope < 0:
            left.append((slope,y_intercept))
        else:
            right.append((slope,y_intercept))

    left_avg = np.average(left,axis = 0)
    right_avg = np.average(right, axis = 0)
    left_line = calculate_coordinates(frame,left_avg)
    right_line = calculate_coordinates(frame,right_avg)
    return np.array([left_line, right_line])
运行程序
cap = cv.VideoCapture("input.mp4")
while (cap.isOpened()):
    # ret = a boolean return value from getting the frame, frame = the current frame being projected in the video
    ret, frame = cap.read()
    canny = do_canny(frame) #canny边缘检测
    cv.imshow("canny", canny)
    # plt.imshow(frame)
    # plt.show()
    segment = do_segment(canny)  #手工分割
    hough = cv.HoughLinesP(segment, 2, np.pi / 180, 100, np.array([]), minLineLength = 100, maxLineGap = 50) #霍夫变换,确定车道线
    # Averages multiple detected lines from hough into one line for left border of lane and one line for right border of lane
    lines = calculate_lines(frame, hough) 
    # Visualizes the lines
    lines_visualize = visualize_lines(frame, lines) #显示车道线
    cv.imshow("hough", lines_visualize)
    # Overlays lines on frame by taking their weighted sums and adding an arbitrary scalar value of 1 as the gamma argument
    output = cv.addWeighted(frame, 0.9, lines_visualize, 1, 1) #车道和原始图片叠加
    # Opens a new window and displays the output frame
    cv.imshow("output", output)
    # Frames are read by intervals of 10 milliseconds. The programs breaks out of the while loop when the user presses the 'q' key
    if cv.waitKey(10) & 0xFF == ord('q'):
        break
# The following frees up resources and closes all windows
cap.release()
cv.destroyAllWindows()
效果图如下
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.canny边缘检测
    • Canny:
    • 2.手动分割路面区域、
    • 3.霍夫变换得到车道线
    • 4.获取车道线并叠加到原始图像中
      • 运行程序
        • 效果图如下
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档