计算机设计大赛无人车挑战赛
计算机设计大赛无人车挑战赛
第1章 作品概述
基于比赛要求,我们结合官方提供的无人车实现模拟道路自主行驶功能。由于可见光视觉容易受到环境干扰等因素,我们充分运用所提供的算力,适当运用深度学习进行目标实现。
在行驶中,无人车首先需要对道路线进行识别。由于无法采用深度信息,我们首先采用计算机传统视觉技术检测车道。我们检测车道像素并拟合以找到车道边界,并确定车道的曲率和车辆相对于中心的位置。最后将检测到的车道边界扭曲回原始图像,并输出车道边界的可视化显示以及车道曲率和车辆位置的数值估计。由于传统算法极易受到光线的影响,因此我们对该算法手动调参,仍然存在一定噪声干扰。
至于各种交通标志、行人和障碍物等进行检测与识别,由于传统视觉对于遮挡、物体分类上识别精度较低,因此我们使用华为云ModelArts云上AI计算方案+华为Hilens端侧AI推理加速的方案。我们基于Hilens Kit边缘设备通过ModelArts平台对各类的物体进行目标检测,且用YoloV3、Fast R-CNN算法附加不同的主干网络进行训练,进行对比和择优。由于行人是否被撞在比赛中极其重要,因此我们选用Hilens Kit边缘设备进行计算加速。
除此之外,无人车还需要对各种交通情况及时地做出相应的行为。我们通过多线程运行,设定优先级的方式对各种方案之间的可能冲突点进行合理消去,实现最优的方案。首先,我们读取摄像头中图片进行目标检测,然后用socket将物体类别、位置信息传输给自带的微型计算机。其次,我们运用互斥锁对无人车的行为进行限制,执行最优的方案,且采用曲率的类似思想控制小车的角度,进而实现小车的行车方向。最后,我们对隧道中做出灯光补充,完善所有可能发生的情况。
在整个备赛过程中,我们同步使用了三种算法适配合适的主干网络,对自己制作的数据集进行测试且对比,并且我们根据结果采用不同算法进行训练,并最后在小车上进行部署。除此之外,我们制作物理赛道进行测试,不断对无人车路径规划算法进行创新性优化,提升整体自主行驶的性能。
第2章 问题描述
无人车在赛场环境下实现准确沿线行驶、礼让行人、按指示牌要求启停的变道,离不开道路分割、行人识别、标志牌识别、决策层判断等核心问题。
2.1 道路分割与车道检测
在自动行驶的过程中,我们需要在纯视觉的情况下进行车道检测和控制,让小车的车轮不会碾压实线。
道路模型如图:
(图1 普通车道模块)
(图2 人行横道模块)
(图3 十字路口模块)
在传统计算机视觉算法中,我们通常对车道线应用颜色和梯度阙值,或者进行透视转换,通过计算车道线的曲率进行巡线行车。但是传统方案存在较大的弊端,比如车道线被其他物体压住会导致识别不全面,其他线条、场外干扰误识别等。对于相似的多条车道线,基于线条阈值检测的方法存在一定的误识别率,并且传统算法对虚线等非连贯性线条错误匹配率较高,可能会导致在车辆变道的时候可能会出现错误变道等现象。
而且从车载摄像头的画面进行视频分析,存在畸变、车道线位置不明显等问题,进一步增加了识别的难度。除此之外,相机在运动的时候会由于快门曝光间隔缠上一定的拖影,从而使车道线视频会有略微模糊,并且在拍摄的时候会产生图像噪声影响识别。
近年来,很多学者逐渐用SegNet网络等深度神经网络对车道线进行语义分割,让小车详细地了解环境并确定车辆可驾驶区域。在之前的工作中,【1】学者通过CNN能够从图像中中提取其中的鲁棒特征,然后通过训练附加的树状回归模型,从特征直接估计车道线的位置,改善传统算法的遮挡弊端。【2】还有学者想方设法剔除运动感车辆、栅栏等带来的误差。
因此,我们采用传统算法改进方法和深度学习进行训练,对比两者的差异。
2.2 道路目标检测
- 红绿灯标志图
(图4 绿灯图)
(图5 黄灯图)
(图6 红灯图) - 路障标志图
(图7 路障标志图) - 停车牌标志图
(图8 停车牌标志图)
(图9 地面标识图)
在自动行驶过程中,我们需要对红绿灯、行人、障碍物、STOP标志牌、地面标识进行识别,实现红灯停、绿灯行,在行人面前停车、障碍物停车或者绕道、STOP标志牌停车、确定小车自身车道的功能。
在纯可见光视觉的限制下,我们不能采用获得深度信息的传感器,所以我们不考虑ros系统。通过计算机视觉知识我们可以知道, 单目摄像头不能测量距离。但由于我们知道各种物品的粗略大小,类似小孔成像原理,在校准之后,我们可以粗略估算出物体的距离。
在实际应用中,目标检测往往需要较高的检测帧率,而传统的基于SVM/Cascade算法很难实现进行实时行人检测。由于车载计算机不配置NVIDIA GPU等因素,传统深度学习框架在CPU上面计算速度较慢,无法达到实时分析的效果。
由于拥有设备资源,我们计划学习和实践基于华为Hilens+ModelArts的AI端云协同解决方案,实现高效率的分类与识别。该方案十分类似paddle方案,ModelArts支持平台上标注,但是modelArts缺少对自动行驶技能开发与封装,对于初学者的我们实在不方便。
在目标检测应用上,由于物体的大小已知,我们固然可以通过解算物体的距离进行判断。但我们也可以极度简化成只要每一类物体到达照片中阙值线则进行对应的行车动作。
2.3 行车规划
车辆需要在车轮不碾压实线的前提下前行,并在十字路口附近正确地识别出地面上的箭头,而后根据道路分割出来的箭头指示进行车辆变道,并考虑变道后是否会与障碍物发生碰撞。在十字路口出要识别出红绿灯的信号,并根据信号做出指示,进而选择是否继续行驶。
在行车规划的时候要同时考虑各种可能发生情况,比如说斑马线的行人是否处于车辆前方,车辆变道的时候是否会与其他车辆发生冲撞,是否正确识别红绿灯并正确转向与前进等等。由于行人生命安全最为重要,我们在行车规划的有限状态下,应着重对行人进行优化。
paddle提供了自动行驶的框架便于我们开发。除此之外,对于这个问题,我们打算有限状态机。由于道路宽度很小,我们规定他以道路的中心进行行驶,根据各种状态以优先级进行判断,实现基本功能。
第3章 技术方案
针对基于视觉的自主驾驶小车赛题,我们从众多要求中提取出三个核心问题,并给出解决方案概括。
3.1 道路分割
采用计算机视觉技术检测车道,执行以下步骤:
给出一组棋盘图像,计算摄像机标定矩阵和畸变系数。对原始图像应用失真校正,并使用颜色变换、渐变等创建阈值二值图像。而后对二值图像应用透视变换来校正二值图像(“鸟瞰图”)。检测车道像素并拟合以找到车道边界,并确定车道的曲率和车辆相对于中心的位置。最后将检测到的车道边界扭曲回原始图像,并输出车道边界的可视化显示以及车道曲率和车辆位置的数值估计。
3.2 道路目标检测
道路目标检测采用华为Hilens+ModelArts端云协同化解决方案,实现“端侧开发,云侧运算”的无缝对接。
ModelArts是一站式AI开发平台,为AI开发提供数据处理及标注、模型训练、端-边-云模型部署等能力。就如Colab与Google云端硬盘,ModelArts平台与对象存储服务 OBS组合实现云端运算,实时部署功能。在平台上,我们可以直接在界面上进行数据集的标注,建立自己的数据集然后选择模型进行训练,测试不同算法之间的差异性。我们在场地中采集数据,在平台上进行不同算法的测试,最终选择最优的物体检测方案。
Hilens Kit是一个华为边缘设备,内置昇腾310系列芯片,可以对计算进行加速。我们将ModelArts模型进行转换,然后在设备上进行安装执行。除此之外,我们在hilens studio上编写自己的代码,然后在设备上实现自定义功能。如我们编写socket将数据传输到minipc上进行数据处理。
3.3 行车规划
在识别出路障,红绿灯,标识,行人等标志物之后,车辆需对于相应的标志物做出一系列的反应来保证自己在符合规定的条件下正常行驶。这里,我们通过整体分类部分与可能冲突情况优先级设置的方法得出小车完整的行车规划方案,让小车在交通规则,目标方向,可能存在的行人与路障等外来因素干扰下顺利行驶,并最终达到目的地。
对于车辆的自动驾驶,我们采用有限状态进行行车判断。我们给予小车一个状态列表,将行车过程中的是否识别出路障、红绿灯、标识、行人等标志物进行汇总,达成初步决策的目的。
除此之外,行车位置规划是行车规划中的重点。为了简化我们先假设速度不变,考虑车的位置与角度之间的变化,而且设定车躲避障碍一定会换道,车沿着车道的中间行驶。
参考人工势场的路径规划方式和传统车道线识别方式,我们可以将物体看成是和车道线一样的东西不可以触碰,由于人工势场十分的复杂,其运算公式不一定能够适应我们的场景,因此我们从同类型联想到我们的传统车道线是用曲率的方式,那避障角度的变化也是可以根据障碍物识别框端点与照片中心之间的角度进行变化。从而实现动态的路径规划。
(图10 行车决策流程图)
第4章 方案实现
4.1 道路分割
基于python3和anaconda实现道路分割,该环境依赖于Python 3.6、Numpy、OpenCV-Python、Matplotlib、Pickle。
运行方法如下:使用python3运行line_fit_video.py。该脚本将读取已录制的project_video.mp4文件,并同时创建一个输出文件out.py。
- 摄像机校正
摄像机校正的时候采用标准棋盘格图片(位于’camera_cal/.jpg’),并将棋盘格图片转化为灰度,并调用OpenCV的findChessboardCorners()函数实现查找棋盘转角。使用96棋盘格对所有校准图像执行上述步骤后,使用OpenCV的caliberecamera()函数计算失真矩阵并使用OpenCV的unormort()函数来消除图像的失真。
(图11 摄像机矫正图) - 图像失真校正
使用’calibrate_camera.p’中的摄像机校正矩阵,对原视频图像进行校正,原图像和校正后的图像如下图所示:
(图12 原图像)
(图13 矫正后图像)
执行摄像机校正的代码位于’calibrate_camera.py’,对于“test_images/.jpg”中的所有图像,该图像的未失真版本将保存在“output_images/unormort.png”中。 - 创建阈值二值图像
下一步是创建阈值二值图像,将未失真图像作为输入。目标是识别可能是车道线一部分的像素。应用下列带阈值的过滤器,以创建与每个单独过滤器相对应的单独“二进制图像”。
图像上的绝对水平Sobel算子
水平和垂直方向上的Sobel算子及其震级计算
Sobel算子计算梯度方向
将图像从RGB空间转换为HLS空间,并设置S通道的阈值
将上述二值图像合并以创建最终的二值图像
下面是示例图像,通过组合上述阈值二值滤波器转换为二值图像:
(图14 二值图像)
生成阈值二值图像的代码是’combined_thresh.py’,尤其是函数combined_thresh()。对于“test_images/.jpg”中的所有图像,该图像的阈值二进制版本保存在“output_images/binary_.png”中。 - 校正二进制图像
给定阈值二值图像,下一步是执行透视变换。我们的目标是转换图像,以便获得车道的“鸟瞰图”,从而使我们能够将曲线拟合到车道线(例如多项式拟合)。这完成的另一件事是“裁剪”原始图像中最有可能具有车道线像素的区域。
为了完成透视图转换,我使用了OpenCV的getPerspectiveTransform()和warpfperspective()函数。我硬编码透视图转换的源和目标点。源点和目的点是通过人工检查目视确定的,尽管一个重要的改进是通过算法确定这些点。
下面是应用透视变换后的示例图像:
(图15 透视变换后图像)
执行透视图转换的代码在’perspective_transform.py’,尤其是函数perspective_transform()。对于“test_images/.jpg”中的所有图像,该图像的扭曲版本(即透视后转换)保存在“output_images/warped_.png”中。 - 图像多项式拟合
给定上一步中扭曲的二值图像,我现在将二阶多项式拟合到左车道线和右车道线,并执行以下操作:
- 计算图像下半部分的直方图
- 将图像分成9个水平切片
- 从底部开始,在直方图的左峰和右峰周围围上一个200像素宽的窗口(垂直将直方图分成两半)
- 向上移动水平窗口切片,找到可能是左右车道一部分的像素,然后机会性地将滑动窗口重新居中
- 给定2组像素(左右车道线候选像素),对每组拟合一个二阶多项式,表示估计的左右车道线
执行上述操作的代码位于’line’的line_fit()函数中’line_fit.py’。
因为我们的目标是从视频流中找到车道线,所以我们可以利用视频帧之间的时间相关性。
给定从先前视频帧计算的多项式拟合,我实现的一个性能增强是从先前预测的车道线水平搜索+/-100像素。然后我们简单地对快速搜索得到的像素进行二阶多项式拟合。如果我们找不到足够的像素,我们可以返回一个错误(例如,返回None),函数的调用者将忽略当前帧(即,保持车道线不变),并确保在下一帧上执行完全搜索。总的来说,这将提高车道检测器的速度,如果我们在生产的自动驾驶汽车中使用此检测器,将非常有用。执行缩写搜索的代码位于’line_py’文件中的’line_fit()‘函数中。
利用时间相关性的另一个增强是平滑多项式拟合参数。这样做的好处是使检测器对噪声输入更加鲁棒。对于最近的5个视频帧,我使用了多项式系数的简单移动平均值(每条车道线3个值)。执行此平滑的代码在文件的类行的函数add_fit()中’Line.py’. Line类被用作这个平滑函数的助手,Line实例是’line_fit.py’。
下面是我们的原始示例图像的多项式拟合输出的图示。对于“test_images/.jpg”中的所有图像,该图像的多项式拟合注释版本将保存在“output_images/polyfit.png”中。
(图16 多项式拟合输出图示)
6. 图像校正与标注
给定左右车道线的多项式拟合,我计算了车辆与车道中心的偏移量。车辆与中心的偏移量在最终视频中进行了注释。当从像素转换为米时,我做了与以前相同的假设。
为了计算车辆与车道线中心的偏移量,我假设车辆的中心是图像的中心。我把车道中心计算为左车道线下x值和右车道线下x值的平均值。偏移量只是车辆的中心x值(即图像的中心x值)减去车道的中心x值。
计算车辆车道偏移量的代码在文件’line_fit.py’中的函数calc_vehicle_offset()。
最后,我们对识别到的车道线进行标注,以便于可视化。我们可以用车道面积、车道曲率和车辆偏移量来标注原始图像。以下是执行此操作的步骤:
- 创建一个空白图像,并绘制我们的多边形拟合线(估计左右车道线)
- 填充线之间的区域(绿色)
- 使用从透视变换计算出的逆扭曲矩阵来“取消”上面的内容,使其与原始图像的透视图对齐
- 在原始图像上覆盖上面的批注
- 向原始图像添加文本以显示车辆偏移
执行上述操作的代码位于’line_fit.py’文件中的函数final_viz()。
下面是我们原始图像的最终注释版本。对于“test_images/.jpg”中的所有图像,该图像的最终注释版本保存在“output_images/annotated_.png”中。
(图17 结果图)
添加完颜色标记,即完成了对车道线的识别。我们将偏置值传入给车辆控制部分,从而实现车道偏离控制。
4.2 道路目标检测
道路目标检测采用基于华为Hilens端云协同AI检测模块。
- 数据集采集
我们用案例代码Data_Coll.py,结合遥控器对数据进行采集,数据自动放置到文件中,由于小车自带的摄像头拍摄的照片十分二点模糊,因为我们在hilens上编写获取图片的代码,用hilens自带摄像头进行读取图片,以及手机进行额外图片的补充。我们将训练所需的数据集图片通过华为的OBS-BROWSER+软件上传至华为OBS对象存储桶中,准备制作数据集。如下图所示:
(图18 数据集制作) - 数据集标注
对于训练集中的图片,我们采用华为云ModelArts,对图像中的行人、红绿灯、地面箭头、交通指示牌进行标注并分类。
(图19 图片标注与分类) - 训练作业与模型建立
我们将AI市场上物体检测模型进行订阅,将同一个训练集用不同的算法进行训练,训练的时候采用华为云推荐的配置,即:8核64GiB CPU,1*nvidia-v100 GPU进行自动化机器学习训练,AI引擎采用TensorFlow,训练成功后即可得到验证所需的模型文件。
(图20 模型训练结果)
而后,我们使用华为云ModelArts自带的部署工具在线对训练好的模型进行部署,验证识别准确率。我们首先将图片在线上进行验证对比之间的准确率,我们甚至可以改动batch参数、轮数以及学习率,对模型进一步训练。最后我们将模型进行转换,准备在进行Hilens端侧的部署和识别。
(图21 在线识别结果)
4.2.4 模型端侧部署
首先我们在hilens studio选择一个模型创建框架,ModelArts将模型转化成om形式,然后导入到hilens studio中的model,在src文件添加自己的代码,然后在设备中进行安装。
(图22 Hilens Studio在线编辑)
4.3 行车规划
- 我们设置向下的摄像头车道线,以及路面箭头等进行识别与分析。对于车道线的识别可以帮助我们的无人车行驶在道路的正确位置以免触线。对于路面箭头的识别会帮助无人车找到正确的方向行驶。
- 我们设置了hilens向前的摄像头对路面上的障碍物、行人、车辆、“STOP”标志、红绿灯进行识别与分析。我们将hilens识别好的数据通过socket传输到minipc上,再进一步进行有限状态机的求解。
- 我们采用一个灯片(灯泡)和光敏电阻实现补光功能。我们通过转动光敏电阻模块上面的滑动变阻器进行阙值的改动,调节到当进入隧道的时候光敏电阻输出高电平,灯从暗变亮。
(图23 补灯测试)
第5章 测试分析
5.1 道路分割
对于源代码我们用我们录制的车道线进行测试发现其遮挡效果不是很好, 除此之外,我们需要对霍夫变换函数进行调参:
1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|
threshold | 90 | 100 | 200 | 300 | 400 |
stn | 700 | 800 | 1000 | 1200 | 1400 |
rank | ✔ |
我们发现,当threshold太大的时候识别出现错误,当threshold = 100,stn= 800是,巡线效果是较好,但是仍然会出现其他噪声标注成车道线。
5.2 道路目标检测
- 数据集的采集
在第一次采集数据的时候,我们采用小车自带的摄像头进行采集,发现十分的模糊,无法作为物体识别的数据集。
(图24 第一次数据集)
我们在hilens上开发一个简单技能,实现对hilens自带摄像头数据的采集数据,以及用手机录像后用软件取帧成图片组成数据集。
(图25 技能局部代码)
(图26 数据集样本) - 模型训练
我们把同一个数据集用不同预置算法继续训练,得到以下表格测试结果。
除此之外,通过上面表格的初步测试,我们还进一步对较优的FastRCNN进行参数的调整,我们发现,如果学习率减小成0.001的时候,物体的准确率提升,但是存在选错对象的状况。因此我们依旧选择学习率为0.002。
(图27 学习率:0.002)
(图28 学习率:0.001)
第6章 作品总结
6.1 作品总结
在此题目中,我们需要设计出一个可以遵循交通规则的自主运行的无人车。在经过对题目分析后,我们从题目中提取出若干技术点,对其进行分析并提出解决方案,再将解决方案合并作为此题的完整解决方案。我们通过多线程运行,设定优先级的方式对于各解决方案之间的可能冲突点进行合理消去,从而让完整的解决方案能运用于小车上完成赛题任务。在停车牌和行人识别方案中,我们使用华为Hilens搭配ModelArts云端计算系统的端云协同AI检测方法,并自主训练停车牌和行人的数据集,相较于颜色识别与形状识别等传统方案来说,提升了停车牌的识别率;我们通过对于道路的分割与规划降低了无人车错误进入其他道路的可能性;我们通过距离感知结合传统识别算法规避了一条道路上的多路障情况等。从测试效果上来说,我们有理由相信我们的无人车可以在保证速度的前提下自主完成赛题。
6.2 未来展望
我们的解决方案在仅使用视觉算法的前提下对于无人车的运行问题进行解决。由于条件等限制原因,目前解决方案存在着一些改进可能:
在此题目中,行人识别的行人训练集较少,若有更多的数据集,则行人识别的准确率能得到提升;我们的测试仅在同一环境下测试,针对着道路上可能出现的各种光线干扰因素,若有实际的环境变量则系统会有更好的鲁棒性;目前,我们在平台上搭建的仅可用于无人小车使用,未来我们希望在增加优化算法的基础之上将算法部署于无人车上,真正意义上的达到对于无人车生活化的开发运用;对于此赛题而言,不允许无人车开始进行建图,未来无人车的实际应用场景下可以加入无人车自动建图,这对于无人车运行与应用问题的解决会有较好的帮助。
随着无人驾驶技术的发展与普及,越来越多的人会加入无人车的研究与开发。此赛题在无人车的自主导航与路线规划实例化上有着启发效果,此次参赛经历对于我们之后无人车方面的学习与实验有着指导意义。我们相信在不久之后,无人车能够真正运用到我们的生活之中,为生活智能化,便捷化助力。