基于多项式拟合和透视变换的车道线检测及曲率计算

本文介绍了基于多项式拟合和透视变换的车道线检测方法,包括图片处理、ROI设置、透视变换、边缘检测、颜色滤波、滑动窗口拟合和曲率计算等步骤。通过KITTI数据集进行处理,用于车道曲率检测和车辆中心偏移量计算。
摘要由CSDN通过智能技术生成

基于多项式拟合和透视变换的车道线检测及曲率计算

        车道线的检测方法有很多,其中具有代表性的有

  • 霍夫变换检测车道线(直线检测效过较好但较容易出现错帧),详见:基于霍夫变换的车道线检测
    在这里插入图片描述

  • 多项式拟合及透视变换检测车道线(可以较好的检测直道弯道,但实时性较差)

在这里插入图片描述

        本文对在工程中更广泛采用的多项式拟合的方法对车道线进行拟合提取,在通过提取到的车道线对弯道进行曲率的检测和车辆与车道线中心的偏移,可以作为以后高级辅助驾驶或者智能驾驶控制感知的前提条件。因此本文采用了KITTI中采集的数据进行处理,可以将其和激光雷达等进行融合处理,得到更加可靠的结果。KITTI中的数据,及图片格式等问题详见:
https://blog.csdn.net/rhyijg/article/details/107775572
        

        大部分文章中,第一部分都是为对摄像头的标定,标定出其内参外参,然后对需要处理的图片进行畸变矫正,本文中使用的KITTI数据集采用已经标定的数据,因此省略此步,有需要的读者可以查询相关资料。

一、对图片的读取操作

        采用opencv对图片进行读取处理,从opencv函数imread()中读取的图片通道格式为BGR,需要对其进行转换成RBG格式,方便后续的处理。同时使用imshow()函数,可以使用鼠标得知当前的像素点,对后续的处理即数据的标定有一定的方便。

from moviepy.editor import VideoFileClip
import matplotlib.pyplot as plt
import matplotlib.image as mplimg
import numpy as np
import cv2
#######################################################################
#                           Main                                      #
#######################################################################
#1读取图片 1280*720
img = cv2.imread('/home/liqi/dev/catkin_ws/src/KITTI_tutorials/2011_09_26_drive_0028_sync/image_02/data/0000000090.png')
# 格式转变,BGRtoRGB
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

cv2.namedWindow('img')
cv2.imshow('img', img)
cv2.waitKey(0)

cv2.destroyAllWindows()

在这里插入图片描述

二、设置检测的ROI区域

        设置检测图片的ROI区域,可以去除噪声和以外的干扰,同时可以加快后续的图片处理速度。选择ROI区域 只保留此区域 其他区域用255填充即全黑。其中的roi_corners = [(550, 215), (698, 215), (825, 374), (385, 374)]为下图梯形中的四个顶点,分别为左上,右上,右下,左下的连接顺序。

# 选择ROI区域 只保留此区域 其他区域用255填充。
def roi_mask(img, vertices):
  #定义mask全为黑
  mask = np.zeros_like(img)
  #defining a 3 channel or 1 channel color to fill the mask with depending on the input image
  if len(img.shape) > 2:
    channel_count = img.shape[2]  # i.e. 3 or 4 depending on your image
    mask_color = (255,) * channel_count
  else:
    mask_color = 255
  #将区域和图片进行填充fillPoly和叠加and
  cv2.fillPoly(mask, vertices, mask_color)
  masked_img = cv2.bitwise_and(img, mask)
  return masked_img

roi_corners = [(550, 215), (698, 215), (825, 374), (385, 374)]
#2、选择ROI区域
roi_vtx = np.array([roi_corners])
roi_mask = roi_mask(img, roi_vtx)

在这里插入图片描述

三、透视变换——鸟瞰图

        我们可以通过透视变换来获得一个相对更加直观的视角(比如说在天空俯视的视角),然后在新的视角来圈出ROI。 透视变换(Perspective Transformation) 是将图片投影到一个新的 视平面(Viewing Plane) ,也称作 投影映射(Projective Mapping) 。在OpenCV中,通过使用函数 cv2.getPerspectiveTransform()cv2.warpPerspective() 即可完成对一张图片的透视变换。

在这里插入图片描述

        cv2.getPerspectiveTransform() 需要两个参数 src 和 dst,他们分别为原图像中能够表示一个矩形的四个点的坐标以及扭曲以后图的边缘四角在当前图像中的坐标,这两个矩形的坐标不同的相机的数值也不同, , 那么[(550, 215), (698, 215), (825, 374), (385, 374)]在图像中构成一个梯形,这个梯形在俯视图(或者说鸟瞰图)中是一个长方形,然后我们以这个梯形的高作为目标图像的高前后各减去一个偏移(在实例中这个偏移是150个像素),就是我们的目标图像这个目标图像,也即是我们的ROI。

        通过透视变换,将上面设置好的ROI区域图片转换成鸟瞰图,将roi_corners作为未变换原图的源坐标及src_corners,然后通过公式即可计算出经过变换后的dst_corners各点坐标;其中wrap_offset = 150为变换的偏移系数,可以通过不断的试验得到最优结果。

3.# 将img转换成鸟瞰图 透视变换(Perspective Transformation)
def perspective_transform(img, M):
    img_size = (img.shape[1], img.shape[0])
    warped = cv2.warpPerspective(img, M, img_size, flags=cv2.INTER_LINEAR)
    return warped

wrap_offset = 150

# 原图像中能够表示一个矩形的四个点的坐标 为实际图像中的车道线选框点
src_corners = roi_corners
dst_corners = [(src_corners[3][0] + wrap_offset, 0), (src_corners[2][0] - wrap_offset, 0), (src_corners[2][0] - wrap_offset, src_corners[2][1]), (src_corners[3][0] + wrap_offset, src_corners[2][1])]
M = cv2.getPerspectiveTransform(np.float32(src_corners), np.float32(dst_corners))
# 透视变换(Perspective Transformation)
wrap_img= perspective_transform(roi_mask, M)

在这里插入图片描述

四、基于sobel 的边缘检测

边缘检测可以使用以下几种算子,对于像车道线识别应用中,需要对高准确度和实时性重点关注,因此可以使用sobel算子进行边缘检测,未来可以使用canny算子进行边缘检测,可以看做是sobel算子的升级版,在文章中基于canny算子的边缘检测有介绍。
在这里插入图片描述在这里插入图片描述

        Sobel是基于梯度图像模值大小的检测算子,通常有水平和垂直两种算子。具体过程如下:

  1. 用一个高斯滤波器平滑图像去除噪声的干扰
  2. 计算梯度幅值图像和角度图像
  3. 对梯度图像应用非最大抑制(保证单一边缘响应)
  4. 对规定方向以外的梯度方向进行非最大抑制
  5. 用双阈值处理和连接分析来检测并连接边缘(保证了低错误率)
  6. 剔除小于阈值的边缘,保留大于阈值的边缘,处于高低阈值之间的边缘点,若其与大于阈值的像素点连接则保留,反之剔除。

        注意在OPENCV中利用调用Sobel函数检测边缘时,应该分别求其水平和垂直两个方向的边缘,再进行加权叠加。

        Sobel函数可选对图像求几阶导数,由实验结果可以看出,二阶导数求出的边缘比一阶更细,这也与之前给出的结论相吻合。

        不难看出, x 方向的索贝尔算子倾向于检测垂直方向的边缘,而 y 方向的索贝尔算子则倾向于检测水平的边缘,而在车道线检测问题中,我们关注的对象(车道线)往往是垂直方向的线,同时我们希望过滤到一些水平方向的线,所以在本实例中,我们采用 x 方向的索贝尔算子。

        通过使用索贝尔算子做两个方向的卷积,我们可以得到图像的每一个像素的横向及纵向 梯度近似值 ,更近一步,我们可以结合这两个近似值计算梯度的大小:
在这里插入图片描述
        然后可用以下公式计算梯度方向:
在这里插入图片描述

# 基于sobel的边缘检测

def abs_sobel_thresh(img, sobel_kernel=3, orient='x', thresh=(0, 255)):
    # 只计算某一方向上的sobel算子检测
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    if orient == 'x':
        sobel = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
    else:
        sobel = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
    abs_sobel = np.absolute(sobel)
    scaled_sobel = np.uint8(255 * abs_sobel / np.max(abs_sobel))
    sxbinary = np.zeros_like(scaled_sobel)
    sxbinary[(scaled_sobel >= thresh[0]
对于一个基于多项式回归的深度学习车道线检测项目来说,需要考虑以下几个步骤: 1. 数据收集和预处理,包括图片采集、图像增强、标注标签等。 2. 特征提取或者特征选择,比如使用边缘检测、颜色过滤等方式提取图像中的特征。 3. 多项式回归模型的搭建和训练。可以使用tensorflow等深度学习框架进行模型搭建和训练。 4. 模型评估和优化,包括模型的准确率、召回率、F1值等指标评价,同时可以使用dropout等方式优化模型的性能。 5. 最终的车道线检测,将模型应用到实际场景中,实现车道线检测的功能。 下面是一个简单的多项式回归模型的代码示例,可以作为其他车道线检测模型的参考: ```python import tensorflow as tf # 定义输入的placeholder X = tf.placeholder(tf.float32, shape=(None, 1)) y = tf.placeholder(tf.float32, shape=(None, 1)) # 定义多项式回归的模型 k = tf.Variable(tf.random_normal([1])) b = tf.Variable(tf.random_normal([1])) y_pred = tf.add(tf.multiply(k, X), b) # 定义损失函数 loss = tf.reduce_mean(tf.square(y_pred - y)) # 定义优化器 optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(loss) # 训练模型 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for i in range(1000): _, l = sess.run([optimizer, loss], feed_dict={X: train_x, y: train_y}) if i % 100 == 0: print("Epoch :", i, " Loss :", l) # 保存模型 saver = tf.train.Saver() saver.save(sess, 'model.ckpt') # 使用训练好的模型进行预测 with tf.Session() as sess: saver = tf.train.Saver() saver.restore(sess, 'model.ckpt') pred_y = sess.run(y_pred, feed_dict={X: test_x}) ```
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值