自动驾驶学习笔记-标记车道

要想让车辆自动行驶在道路上就要让车辆能够感知周围,例如使用传感器感知周围物体与自己的距离和相对速度,定位自身位置,通过摄像头识别周围物体的类型或交通标志,并调整行驶的速度和方向。本文对摄像头记录的道路视频进行处理,识别车道线,以使车辆在车道内行驶,避免越界,确保行驶安全。这是对udacity self-driving 第一个项目find lane line的总结,主要内容包括给出从原始图片到在其中标记车道线的一般流程,并给出每一个步python源码和处理后效果图。

标记道路的流程

算法对道路图像的处理流程可以分为以下步骤:

  1. 灰度处理
  2. 高斯模糊
  3. 边缘检测
  4. 选择目标区域
  5. 霍夫曼变换
    自动驾驶学习笔记-标记车道_第1张图片

灰度处理将源图片转换为灰度,高斯平滑消除图片的噪点,再用canny边缘检测算法识别图像中物体的边界。

一副图像中亮度快速变化的地方被当作边沿,canny边沿检测算法的原理是对一副图片的每个像素点的各个方向求导数,导数越大表明变化速度越大,选出每个点各个方向最大导数得到一个同尺寸的二维数组,然后通过调节canny算法的参数将符合条件的导数值标记出来组成物体的边界。canny算法的参数low_threshold, 和high_threshold选出物体边界。选出大于high_threshold的值,祈祷片小于low_threshold的点, 处于两者之间的值并与已选出的值相邻则继续选中,否则忽略。

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
import cv2

image = mpimg.imread('gray.jpg')
#灰度处理
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

#高斯平滑
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size), 0)

#边缘检测
low_threshold = 50
high_threshold = 150
edges = cv2.Canny(blur_gray, low_threshold, high_threshold)

plt.imshow(edges)

自动驾驶学习笔记-标记车道_第2张图片

经过canny边界检测算法之后可以看到整幅图中除了车道线以外还有一些无关的边界,这些边界对标记车道线没有帮助,所以使用掩码去掉无关的区域。

def region_of_interest(img, vertices):
    mask = np.zeros_like(img)   
    if len(img.shape) > 2:
        channel_count = img.shape[2] 
        ignore_mask_color = (10,) * channel_count
    else:
        ignore_mask_color = 10
    cv2.fillPoly(mask, vertices, ignore_mask_color)
    masked_image = cv2.bitwise_and(img, mask)
    return masked_image

vertices = np.array([[(200,470),(400, 340), (520, 320), (820,470)]], dtype=np.int32)
region_of_interest(img, vertices)

自动驾驶学习笔记-标记车道_第3张图片
选择目标区域后对其进行霍夫曼变换处理,霍夫曼变换是一种检测物体形状的常用方法,霍夫曼变换的基本原理是将(x,y)的二维空间映射到表示斜率和截距的霍夫曼空间 ( k , b ) (k,b) (k,b), 这样,原二维空间中的每个点在霍夫曼空间中都可以表示为一条直线,然后霍夫曼变换再采用投票算法,将所有直线的交点计数,选出总数超过阈值的交点 ( k , b ) (k,b) (k,b)在原二维空间中就可以表示一条直线。由于霍夫曼空间 ( k , b ) (k,b) (k,b)无法表示x轴的垂线,所以一般用 ( ρ , θ ) ( \rho,\theta) (ρθ)的霍夫曼平面代替。
使用霍夫曼变换可以直接调用opencv中的HoughLinesP( image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]] )
其中几个重要参数的意义分别为:一条直线上点的数量小于theta会被忽略,一条线的长度小于minLineLength也会被忽略,两个线段在一条直线上,之间的空隙如果小于maxLineGap,则会被自动连接。

def draw_lanes(lines):
    left_lines=[]
    right_lines = []
    for line in lines:
        for x1,y1,x2,y2 in line:
            slope = (y2-y1)/(x2-x1)
            if slope<0:
                left_lines.append([[x1,y1,x2,y2]])
            elif slope>0:
                right_lines.append([[x1,y1,x2,y2]])
    if(len(left_lines)<1):
        print('something thing wrong in left')
    if(len(right_lines)<1):
        print('something thing wrong in right')
    clean_lines(left_lines)
    clean_lines(right_lines)

    left_vertices=calc_lane_vertices(left_lines,325,540)
    right_vertices = calc_lane_vertices(right_lines,325,540)
    return left_vertices,right_vertices
    
def hough_lines(img, rho, theta, threshold, min_line_len, max_line_gap,advance = False):
    lines = cv2.HoughLinesP(img, rho, theta, threshold, np.array([]), minLineLength=min_line_len, maxLineGap=max_line_gap)**
    plt.imshow(lines)
    lines_img = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
    draw_lines(lines_img, lines)
    return lines_img
    
lines = hough_lines(masked_edges,rho,theta,threshold,min_line_length,max_line_gap,True)
plt.imshow(lines)
mpimg.imsave('resualt/lines',lines)

自动驾驶学习笔记-标记车道_第4张图片

最后将标记了车道的图片和源图片叠加,可以看到车道已经被清晰的标注。
自动驾驶学习笔记-标记车道_第5张图片
以上便是我在学习udaciy自动驾驶课程中对寻找车道线这一项目的一次总结,主要内容包括寻找车道线的一般处理流程,解释了canny边沿检测和霍夫曼变换的一般原理,给出了每一步流程的实现源码和效果图。

你可能感兴趣的:(自动驾驶)