基于OPENCV和YOLOv5的自动驾驶技术

这篇具有很好参考价值的文章主要介绍了基于OPENCV和YOLOv5的自动驾驶技术。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:这是我机器学习的课程设计,实现的是在YOLOv5目标检测的基础上增加语义分割头,然后在Cityscapes数据集上进行训练,代码参考的是TomMo23链接如下:TomMao23/multiyolov5: joint detection and semantic segmentation, based on ultralytics/yolov5, (github.com)在此基础上,增加了车道检测并计算车道的曲率半径,同时计算车辆偏离车道中心的距离,也可计算出识别出的车辆距离本车辆的距离。项目主要分为两大块内容:用传统方法即opencv通过图像矫正、二值化、图像变换对二值化图像进行梯度阈值过滤和颜色阈值过滤然后进行二次函数拟合识别出车道线;第二块内容就是YOLOv5识别各种车辆和交通灯。

一、车道检测

1.1.相机矫正

由于拍摄得到的图像可能存在畸变,或者不正的情况,所以在做后面的步骤前需要进行相机矫正,这边使用了opencv中的calibrateCamera()方法拍摄相当数量不同角度和品质的棋盘格图像来得到相机标定矩阵。

def get_obj_img_points(images,grid=(9,6)):
    object_points=[]
    img_points = []
    for img in images:
        #生成object points
        object_point = np.zeros( (grid[0]*grid[1],3),np.float32 )
        object_point[:,:2]= np.mgrid[0:grid[0],0:grid[1]].T.reshape(-1,2)
        #得到灰度图片
        gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        #得到图片的image points
        ret, corners = cv2.findChessboardCorners(gray, grid, None)
        if ret:
            object_points.append(object_point)
            img_points.append(corners)
    return object_points,img_points

然后把上述的参数传入cv的calibrateCamera() 方法中就可以计算出相机校正矩阵(camera calibration matrix)和失真系数(distortion coefficients),再使用 cv2.undistort()方法就可得到校正图片。     

def cal_undistort(img, objpoints, imgpoints):
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, img.shape[1::-1], None, None)
    dst = cv2.undistort(img, mtx, dist, None, mtx)
    return dst

1.2阈值过滤

在经过相机矫正后继续经过阈值过滤可以得到清晰捕捉车道线的二进制图,经过几种阈值处理方法最后决定同时使用梯度阈值和颜色阈值过滤的方法。采用水平梯度变化,通过测试发现方向阈值在35到100区间过滤得出的二进制图可以捕捉较为清晰的车道线。实现代码如下:

def abs_sobel_thresh(img, orient='x', thresh_min=0, thresh_max=255):
    # Convert to grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    # Apply x or y gradient with the OpenCV Sobel() function
    # and take the absolute value
    if orient == 'x':
        abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 1, 0))
    if orient == 'y':
        abs_sobel = np.absolute(cv2.Sobel(gray, cv2.CV_64F, 0, 1))
    # Rescale back to 8 bit integer
    scaled_sobel = np.uint8(255 * abs_sobel / np.max(abs_sobel))
    # Create a copy and apply the threshold
    binary_output = np.zeros_like(scaled_sobel)
    # Here I'm using inclusive (>=, <=) thresholds, but exclusive is ok too
    binary_output[(scaled_sobel >= thresh_min) & (scaled_sobel <= thresh_max)] = 1

    # Return the result
    return binary_output

def hls_select(img, channel='s', thresh=(0, 255)):
    hls = cv2.cvtColor(img, cv2.COLOR_RGB2HLS)
    if channel == 'h':
        channel = hls[:, :, 0]
    elif channel == 'l':
        channel = hls[:, :, 1]
    else:
        channel = hls[:, :, 2]
    binary_output = np.zeros_like(channel)
    binary_output[(channel > thresh[0]) & (channel <= thresh[1])] = 1
    return binary_output

1.3车道检测

首先要定位车道线的基点(图片最下方车道出现的x轴坐标),由于车道线在的像素都集中在x轴一定范围内,因此把图片一分为二,则左右两边的在x轴上的像素分布峰值非常有可能就是车道线基点。

基于OPENCV和YOLOv5的自动驾驶技术

 沿x轴对图像进行采样,当白色像素点急剧变化的地方就认为是车道线所在的位置。

def find_line_by_previous(binary_warped, left_fit, right_fit):
    nonzero = binary_warped.nonzero()
    nonzeroy = np.array(nonzero[0])
    nonzerox = np.array(nonzero[1])
    margin = 100
    left_lane_inds = ((nonzerox > (left_fit[0] * (nonzeroy ** 2) + left_fit[1] * nonzeroy +
                                   left_fit[2] - margin)) & (nonzerox < (left_fit[0] * (nonzeroy ** 2) +
                                                                         left_fit[1] * nonzeroy + left_fit[
                                                                             2] + margin)))

    right_lane_inds = ((nonzerox > (right_fit[0] * (nonzeroy ** 2) + right_fit[1] * nonzeroy +
                                    right_fit[2] - margin)) & (nonzerox < (right_fit[0] * (nonzeroy ** 2) +
                                                                           right_fit[1] * nonzeroy + right_fit[
                                                                               2] + margin)))

    # Again, extract left and right line pixel positions
    leftx = nonzerox[left_lane_inds]
    lefty = nonzeroy[left_lane_inds]
    rightx = nonzerox[right_lane_inds]
    righty = nonzeroy[right_lane_inds]
    # Fit a second order polynomial to each
    left_fit = np.polyfit(lefty, leftx, 2)
    right_fit = np.polyfit(righty, rightx, 2)
    return left_fit, right_fit, left_lane_inds, right_lane_inds

还可以得到一个带x轴索引的y方向像素均值元组,可以将其作为拟合曲线的x,y输入numpy的polyfit()方法产生拟合曲线。 然后确定每像素与在世界坐标中距离的对应关系,基于此对应关系和上述产生的拟合曲线结合生成新的拟合曲线,此拟合曲线反应的是显示车道线,再代入公式 然后计算偏离中心位置的距离,由于前面所有对于图像处理的过程关系,此处可以近似将图像二值图像中心的x值,将其与每像素与在世界坐标中距离的对应关系相乘,此值与未经过对应关系转换的拟合曲线的最后一个值,经过对应关系转换的差值就是偏离车道中心的实际距离。 使用逆变形矩阵把鸟瞰二进制图检测的车道镶嵌回原图,并高亮车道区域,使用opencv的putText()方法处理原图展示车道曲率及车辆相对车道中心位置信息

def draw_area(undist, binary_warped, Minv, left_fit, right_fit):
    # Generate x and y values for plotting
    ploty = np.linspace(0, binary_warped.shape[0] - 1, binary_warped.shape[0])
    left_fitx = left_fit[0] * ploty ** 2 + left_fit[1] * ploty + left_fit[2]
    right_fitx = right_fit[0] * ploty ** 2 + right_fit[1] * ploty + right_fit[2]
    # Create an image to draw the lines on
    warp_zero = np.zeros_like(binary_warped).astype(np.uint8)
    color_warp = np.dstack((warp_zero, warp_zero, warp_zero))

    # Recast the x and y points into usable format for cv2.fillPoly()
    pts_left = np.array([np.transpose(np.vstack([left_fitx, ploty]))])
    pts_right = np.array([np.flipud(np.transpose(np.vstack([right_fitx, ploty])))])
    pts = np.hstack((pts_left, pts_right))

    # Draw the lane onto the warped blank image
    cv2.fillPoly(color_warp, np.int_([pts]), (0, 255, 0))

    # Warp the blank back to original image space using inverse perspective matrix (Minv)
    newwarp = cv2.warpPerspective(color_warp, Minv, (undist.shape[1], undist.shape[0]))
    # Combine the result with the original image
    result = cv2.addWeighted(undist, 1, newwarp, 0.3, 0)
    return result


#   计算曲率和半径
def calculate_curv_and_pos(binary_warped, left_fit, right_fit):
    # Define y-value where we want radius of curvature
    ploty = np.linspace(0, binary_warped.shape[0] - 1, binary_warped.shape[0])
    leftx = left_fit[0] * ploty ** 2 + left_fit[1] * ploty + left_fit[2]
    rightx = right_fit[0] * ploty ** 2 + right_fit[1] * ploty + right_fit[2]
    # Define conversions in x and y from pixels space to meters
    ym_per_pix = 30 / 720  # meters per pixel in y dimension
    xm_per_pix = 3.7 / 700  # meters per pixel in x dimension
    y_eval = np.max(ploty)
    # Fit new polynomials to x,y in world space
    left_fit_cr = np.polyfit(ploty * ym_per_pix, leftx * xm_per_pix, 2)
    right_fit_cr = np.polyfit(ploty * ym_per_pix, rightx * xm_per_pix, 2)
    # Calculate the new radii of curvature
    left_curverad = ((1 + (2 * left_fit_cr[0] * y_eval * ym_per_pix + left_fit_cr[1]) ** 2) ** 1.5) / np.absolute(
        2 * left_fit_cr[0])
    right_curverad = ((1 + (2 * right_fit_cr[0] * y_eval * ym_per_pix + right_fit_cr[1]) ** 2) ** 1.5) / np.absolute(
        2 * right_fit_cr[0])

    curvature = ((left_curverad + right_curverad) / 2)
    # print(curvature)
    lane_width = np.absolute(leftx[719] - rightx[719])
    lane_xm_per_pix = 3.7 / lane_width
    veh_pos = (((leftx[719] + rightx[719]) * lane_xm_per_pix) / 2.)
    cen_pos = ((binary_warped.shape[1] * lane_xm_per_pix) / 2.)
    distance_from_center = cen_pos - veh_pos
    return curvature, distance_from_center


def calculate_position(bbox, transform_matrix, warped_size, pix_per_meter):
    if len(bbox) == 0:
        print("nothing")
    else:
        pos = np.array((bbox[1] / 2 + bbox[3] / 2, bbox[2])).reshape(1, 1, -1)
        dst = cv2.perspectiveTransform(pos, transform_matrix).reshape(-1, 1)
        return np.array((warped_size[1] - dst[1]) / pix_per_meter[1])

def draw_values(img, curvature, distance_from_center):
    font = cv2.FONT_HERSHEY_SIMPLEX
    radius_text = "Radius of Curvature: %sm" % (round(curvature))

    if distance_from_center > 0:
        pos_flag = 'right'
    else:
        pos_flag = 'left'

    cv2.putText(img, radius_text, (100, 100), font, 1, (255, 255, 255), 2)
    center_text = "Vehicle is %.3fm %s of center" % (abs(distance_from_center), pos_flag)
    cv2.putText(img, center_text, (100, 150), font, 1, (255, 255, 255), 2)
    return img

二、YOLOV5

YOLOv5是一种单阶段目标检测算法,该算法在YOLOv3的基础上添加了一些新的改进思路:使用Pytorch框架更容易投入生产,整合了计算机视觉领域的State-of-the-art等算法

由于训练需要的图片数据庞大,所以训练集图片我们使用的是国外数据集Cityscapes,即城市景观数据集,该数据集拥有5000张在城市环境中驾驶场景的图像。在本次训练中我们用2975张图片作为训练集,500张作为验证集,1525张图片作为测试集。

本次实验训练的模型在Cityscapes语义分割数据集和由Cityscapes实例分割标签转换来的目标检测数据集上同时训练,这样就可以在进行目标检测的同时同时进行语义分割。

这部分的代码和配置过程TomMo的readme里面已经写得很清楚了,我这边就不在赘述了,大家按他的教程来一般就可以训练自己的模型出来。

我最后就放一下我最后的效果吧~

YOLOv5自动驾驶文章来源地址https://www.toymoban.com/news/detail-478017.html

到了这里,关于基于OPENCV和YOLOv5的自动驾驶技术的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • YOLOV5 自动刷图脚本实战(六)之OpenCV+CMake+MinGW-64 Qt5编译

    目录  一、OpenCV下载 1、官网地址: 2、安装解压OpenCV 二、OpenCV-Contrib下载 1、下载

    2024年02月03日
    浏览(44)
  • 基于深度学习的安全帽识别检测系统(python OpenCV yolov5)

    收藏和点赞,您的关注是我创作的动力    基于深度学习算法,以PaddlePaddle深度学习框架作为实验环境,选取了开源的安全帽识别数据库和实地拍摄的安全帽佩戴照片,使用样本扩增增加了实验数据集的样本数,选取了Faster R-CNN、SSD与YOLO v3三种深度神经网络模型,构建出安

    2024年02月08日
    浏览(44)
  • 目标检测YOLO实战应用案例100讲-基于改进YOLOv4算法的自动驾驶场景 目标检测

    目录 前言 国内外目标检测算法研究现状  传统目标检测算法的发展现状 

    2024年02月06日
    浏览(54)
  • 基于树莓派Qt+opencv+yolov5-Lite+C++部署深度学习推理

            本文是基于 qt和opencv的dnn 深度学习推理模块,在树莓派上部署YOLO系列推理,适用于yolov5-6.1以及yolov5-Lite,相比直接用python的onnxruntime,用基于opencv的dnn模块,利用训练生成的onnx模型,即可快速部署,不需要在树莓派上额外安装深度学习的一系列环境,因为我们知道

    2024年04月16日
    浏览(65)
  • 8. 《自动驾驶与机器人中的SLAM技术》基于保存的自定义NDT地图文件进行自动驾驶车辆的激光定位

    目录 1. 为 NDT 设计一个匹配度评估指标,利用该指标可以判断 NDT 匹配的好坏。 2. 利用第 1 题的指标,修改程序,实现 mapping 部分的回环检测。 3. 将建图结果导出为 NDT map,即将 NDT 体素内的均值和协方差都存储成文件。 4. 实现基于 NDT map 的激光定位。根据车辆实时位姿,

    2024年02月02日
    浏览(42)
  • 疲劳驾驶检测系统-YOLOv8/YOLOv7/YOLOv5-疲劳检测、分心检测、玩手机、抽烟、喝水检测(毕业设计)

    本项目效果展示视频: https://www.bilibili.com/video/BV1bj411S7rA/?share_source=copy_webvd_source=138d2e7f294c3405b6ea31a67534ae1a 1、本项目通过YOLOv8/YOLOv7/YOLOv5、Dlib和PySide2实现了一个疲劳驾驶检测系统,可为一些同学的课设、大作业等提供参考。该项目分为两个检测部分,疲劳检测和分心行为检测

    2024年02月05日
    浏览(51)
  • 疲劳驾驶检测系统-YOLOv5-疲劳检测、分心检测、玩手机、抽烟、喝水检测(毕业设计)

    本项目效果展示视频: https://www.bilibili.com/video/BV1bj411S7rA/?share_source=copy_webvd_source=138d2e7f294c3405b6ea31a67534ae1a 1、本项目通过YOLOv8/YOLOv7/YOLOv5、Dlib和PySide2实现了一个疲劳驾驶检测系统,可为一些同学的课设、大作业等提供参考。该项目分为两个检测部分,疲劳检测和分心行为检测

    2024年02月10日
    浏览(41)
  • OpenCV之YOLOv5目标检测

    💂 个人主页: 风间琉璃 🤟 版权:  本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主 💬 如果文章对你有帮助、 欢迎关注、 点赞、 收藏(一键三连) 和 订阅专栏 哦 目录 前言 一、YOLOv5简介 二、预处理 1.获取分类名 2.获取输出层名称 3.图像尺度变换 三、模型加载

    2024年01月20日
    浏览(56)
  • QT+Opencv+yolov5实现监测

    功能说明:使用QT+Opencv+yolov5实现监测 =============================== 仓库链接:https://gitee.com/wangyoujie11/qt_yolov5.git git本仓库到本地 一、环境配置 1.opencv配置 将OpenCV-MinGW-Build-OpenCV-4.5.2-x64文件夹放在自己的一个目录下,如我的路径: 编辑系统环境变量【配置完成之后,要 确定 】

    2024年04月11日
    浏览(41)
  • 自动驾驶技术综述1:自动驾驶算法软件架构介绍

    前言: 自动驾驶技术是一个庞大的工程体系,软件架构、功能算法、控制规划、感知识别、建图定位、电气架构、车载控制器、验证体系等等,有太多的角度可以去切入。对于自动驾驶功能与算法开发,自动驾驶功能的分级是很重要的,自动驾驶的功能衍变就是随着自动驾驶

    2024年02月06日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包