智慧交通day03-车道线检测实现04:车道线提取原理+代码实现+效果图

简介: 在车道线检测中,我们使用的是HSL颜色空间,其中H表示色相,即颜色,S表示饱和度,即颜色的纯度,L表示颜色的明亮程度。

我们基于图像的梯度和颜色特征,定位车道线的位置。


在这里选用Sobel边缘提取算法,Sobel相比于Canny的优秀之处在于,它可以选择横向或纵向的边缘进行提取。从车道的拍摄图像可以看出,我们关心的正是车道线在横向上的边缘突变。OpenCV提供的cv2.Sobel()函数,将进行边缘提取后的图像做二进制图的转化,即提取到边缘的像素点显示为白色(值为1),未提取到边缘的像素点显示为黑色(值为0)。由于只使用边缘检测,在有树木阴影覆盖的区域时,虽然能提取出车道线的大致轮廓,但会同时引入的噪声,给后续处理带来麻烦。所以在这里我们引入颜色阈值来解决这个问题。


1.颜色空间


在车道线检测中,我们使用的是HSL颜色空间,其中H表示色相,即颜色,S表示饱和度,即颜色的纯度,L表示颜色的明亮程度。


HSL的H(hue)分量,代表的是人眼所能感知的颜色范围,这些颜色分布在一个平面的色相环上,取值范围是0°到360°的圆心角,每个角度可以代表一种颜色。色相值的意义在于,我们可以在不改变光感的情况下,通过旋转色相环来改变颜色。在实际应用中,我们需要记住色相环上的六大主色,用作基本参照:360°/0°红、60°黄、120°绿、180°青、240°蓝、300°洋红,它们在色相环上按照60°圆心角的间隔排列:


35f537d6697d46a493f595c6f50cbae4.png


HSL的S(saturation)分量,指的是色彩的饱和度,描述了相同色相、明度下色彩纯度的变化。数值越大,颜色中的灰色越少,颜色越鲜艳,呈现一种从灰度到纯色的变化。因为车道线是黄色或白色,所以利用s通道阈值来检测车道线。


4b2a06dcfb2544abbdfb591a3b650cc3.png


HSL的L(lightness)分量,指的是色彩的明度,作用是控制色彩的明暗变化。数值越小,色彩越暗,越接近于黑色;数值越大,色彩越亮,越接近于白色。


961fa8c005d648349d9e28f62371309d.png


2.车道线提取


车道线提取的代码如下所示:


# 车道线提取代码
def pipeline(img, s_thresh=(170, 255), sx_thresh=(40, 200)):
    img = np.copy(img)
    #1.将图像转换为HLS色彩空间,并分离各个通道
    hls = cv2.cvtColor(img, cv2.COLOR_RGB2HLS).astype(np.float)
    h_channel = hls[:, :, 0]
    l_channel = hls[:, :, 1]
    s_channel = hls[:, :, 2]
    #2.利用sobel计算x方向的梯度
    sobelx = cv2.Sobel(l_channel, cv2.CV_64F, 1, 0)
    abs_sobelx = np.absolute(sobelx) 
    # 将导数转换为8bit整数
    scaled_sobel = np.uint8(255 * abs_sobelx / np.max(abs_sobelx))
    sxbinary = np.zeros_like(scaled_sobel)
    sxbinary[(scaled_sobel >= sx_thresh[0]) & (scaled_sobel <= sx_thresh[1])] = 1
    # 3.对s通道进行阈值处理
    s_binary = np.zeros_like(s_channel)
    s_binary[(s_channel >= s_thresh[0]) & (s_channel <= s_thresh[1])] = 1
    # 4. 将边缘检测的结果和颜色空间阈值的结果合并,并结合l通道的取值,确定车道提取的二值图结果
    color_binary = np.zeros_like(sxbinary)
    color_binary[((sxbinary == 1) | (s_binary == 1)) & (l_channel > 100)] = 1
    return color_binary


我们来看下整个流程:


首先我们是把图像转换为HLS颜色空间,然后利用边缘检测和阈值的方法检测车道线,我们以下图为例,来看下检测结果:


3fcbe5a7d72f4e56a073154ca879fe21.png


  • 利用sobel边缘检测的结果


78cb96899f484f3ba5536bd0b8df83b0.png


  • 利用S通道的阈值检测结果


a01ad6dab3a9460fa9f0151d2d874603.png


  • 将边缘检测结果与颜色检测结果合并,并利用L通道抑制非白色的信息:


5304a18f840647718cec107e4e825903.png


总结:


1.颜色空间:


HLS:色相,饱和度,明亮程度


2.车道线提取


颜色空间转换-》边缘检测-》颜色阈值-》合并得到检测结果。


代码:


# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#遍历文件夹
import glob
from moviepy.editor import VideoFileClip
"""参数设置"""
nx = 9
ny = 6
#获取棋盘格数据
file_paths = glob.glob("./camera_cal/calibration*.jpg")
# 绘制对比图
def plot_contrast_image(origin_img, converted_img, origin_img_title="origin_img", converted_img_title="converted_img",
                        converted_img_gray=False):
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 20))
    ax1.set_title = origin_img_title
    ax1.imshow(origin_img)
    ax2.set_title = converted_img_title
    if converted_img_gray == True:
        ax2.imshow(converted_img, cmap="gray")
    else:
        ax2.imshow(converted_img)
    plt.show()
#相机矫正使用opencv封装好的api
#目的:得到内参、外参、畸变系数
def cal_calibrate_params(file_paths):
    #存储角点数据的坐标
    object_points = [] #角点在真实三维空间的位置
    image_points = [] #角点在图像空间中的位置
    #生成角点在真实世界中的位置
    objp = np.zeros((nx*ny,3),np.float32)
    #以棋盘格作为坐标,每相邻的黑白棋的相差1
    objp[:,:2] = np.mgrid[0:nx,0:ny].T.reshape(-1,2)
    #角点检测
    for file_path in file_paths:
        img = cv2.imread(file_path)
        #将图像灰度化
        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        #角点检测
        rect,coners = cv2.findChessboardCorners(gray,(nx,ny),None)
        #若检测到角点,则进行保存 即得到了真实坐标和图像坐标
        if rect == True :
            object_points.append(objp)
            image_points.append(coners)
    # 相机较真
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(object_points, image_points, gray.shape[::-1], None, None)
    return ret, mtx, dist, rvecs, tvecs
# 图像去畸变:利用相机校正的内参,畸变系数
def img_undistort(img, mtx, dist):
    dis = cv2.undistort(img, mtx, dist, None, mtx)
    return dis
#车道线提取
#颜色空间转换--》边缘检测--》颜色阈值--》并且使用L通道进行白色的区域进行抑制
def pipeline(img,s_thresh = (170,255),sx_thresh=(40,200)):
    # 复制原图像
    img = np.copy(img)
    # 颜色空间转换
    hls = cv2.cvtColor(img,cv2.COLOR_RGB2HLS).astype(np.float)
    l_chanel = hls[:,:,1]
    s_chanel = hls[:,:,2]
    #sobel边缘检测
    sobelx = cv2.Sobel(l_chanel,cv2.CV_64F,1,0)
    #求绝对值
    abs_sobelx = np.absolute(sobelx)
    #将其转换为8bit的整数
    scaled_sobel = np.uint8(255 * abs_sobelx / np.max(abs_sobelx))
    #对边缘提取的结果进行二值化
    sxbinary = np.zeros_like(scaled_sobel)
    #边缘位置赋值为1,非边缘位置赋值为0
    sxbinary[(scaled_sobel >= sx_thresh[0]) & (scaled_sobel <= sx_thresh[1])] = 1
    plt.figure()
    plt.imshow(sxbinary, cmap='gray')
    plt.title("sobel")
    plt.show()
    #对S通道进行阈值处理
    s_binary = np.zeros_like(s_chanel)
    s_binary[(s_chanel >= s_thresh[0]) & (s_chanel <= s_thresh[1])] = 1
    plt.figure()
    plt.imshow(s_binary, cmap='gray')
    plt.title("schanel")
    plt.show()
    # 结合边缘提取结果和颜色通道的结果,
    color_binary = np.zeros_like(sxbinary)
    color_binary[((sxbinary == 1) | (s_binary == 1)) & (l_chanel > 100)] = 1
    return color_binary
if __name__ == "__main__":
    #测试车道线提取
    img = cv2.imread('./test/test3.jpg')
    result = pipeline(img)
    plot_contrast_image(img, result, converted_img_gray=True)


代码输出:


1.原图


7fe36e38a722411fa73092fb093a7de2.png


2.sobel之后


56580755cef44914bc044c61f37833e6.png


3.schanel


be2538b84d6c4ce4a34848a043bc20ee.png



 4.处理完毕对比图


966ef83a69a24803956a5bac04c15b63.png

目录
相关文章
|
算法
轨迹系列——一种基于中值滤波的轨迹纠偏方法和几点思考
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 在无路网的情况下,如何进行轨迹纠偏也是一个很多人在研究的内容,各种方案均有很多,有基于不同滤波算法的,也有基于机器学习的,等等。
2931 0
|
7月前
|
机器学习/深度学习 传感器 算法
目标检测+车道线识别+追踪+测距(代码+部署运行)
目标检测+车道线识别+追踪+测距(代码+部署运行)
|
存储 编解码 定位技术
案例!从天地图中提取全市的建筑物矢量轮廓-以苏州市为例
案例!从天地图中提取全市的建筑物矢量轮廓-以苏州市为例
240 1
|
算法 计算机视觉
指针式仪表的表盘自动识别算法
指针式仪表的表盘自动识别算法
1886 0
指针式仪表的表盘自动识别算法
|
机器学习/深度学习 算法
【目标识别】检测具有相同背景的不同图像并找到图像中的红色圆圈目标(Matlab代码实现)
【目标识别】检测具有相同背景的不同图像并找到图像中的红色圆圈目标(Matlab代码实现)
|
自动驾驶 算法 Python
车道线识别(附代码)
车道线识别(附代码)
车道线识别(附代码)
|
机器学习/深度学习 传感器 编解码
【车道线检测】基于计算机视觉实现车道线视频检测附matlab代码
【车道线检测】基于计算机视觉实现车道线视频检测附matlab代码
|
智慧交通
智慧交通day03-车道线检测实现06:车道线定位及拟合+代码实现
我们根据前面检测出的车道线信息,利用直方图和滑动窗口的方法,精确定位车道线,并进行拟合。
262 0
|
智慧交通
智慧交通day03-车道线检测实现05:透视变换+代码实现
为了方便后续的直方图滑窗对车道线进行准确的定位,我们在这里利用透视变换将图像转换成俯视图,也可将俯视图恢复成原有的图像
183 0
|
智慧交通
智慧交通day03-车道线检测实现09:车道线检测代码汇总(Python3.8)
智慧交通day03-车道线检测实现09:车道线检测代码汇总(Python3.8)
108 0