完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
`编程设计了一个由 Raspberry Pi、Arduino Uno 和一个树莓派摄像头组成的自动驾驶机器人小车。通过使用 Python、C++ 和神经网络进行图像处理,并以 60 FPS 的速度实时运行。 在这篇文章中,我们将对这个项目做完整的介绍,并给出复现设计该智能小车的关键要点。 软硬件清单
硬件清单: 1. 小车底盘 2. 树莓派3 + 树莓派摄像头 3. Arduino Uno + Arduino原型板 4. 直流电机控制器 5. 3D打印零部件 - 电池盒 - 摄像头固定柱 - 摄像头固定夹 - 树莓派固定盒 6. 伺服电机 7. 紧急停止按钮开关 8. 电池:用于电机的原装Nikko电池 + 树莓派与Arduino的外部供电电池 软件清单: 1. Arduino:C++ 2. 树莓派:Python +Numpy + OpenCV 3. 神经网络训练:Lasagne +Theano 4. Arduino <-> 树莓派通信:自制串口协议 程序框图与仿真
如图显示,项目的图像处理和小车控制部分是在Raspberry Pi上完成的。 树莓派与Arduino之间建立串行协议通信,由后者使用PWM向电机发送指令(方向和速度)。由于Arduino没有提供串口写入的有效方式,为了使两块板卡之间可以进行通信,这里我们使用了一种自制的串行协议,基于单字节写入Arduino方法Serial.write()。协议如下:首先发送一个长度为1个字节(8位)的指令,然后每个字节逐一发送所需的参数。这里我们使用了一些方法来对长度为整数1-4个字节的指令进行编码和解码。例如,当发送一个16位的int时,我们把它分成两个字节(每个8位),并将这些字节存储在一个缓冲区数组中。然后,我们发送缓冲区中的每个字节,并在接收时使用按位操作(移位和屏蔽)来重建16位。 过程中,我们同时考虑到了Arduino有限的缓冲区大小:如果我们在短时间内发送太多的字节,部分信息将会因此而丢失。为了避免这个问题,Arduino通过反馈一条“收到”消息来确认收到每一条指令。这个“收到”消息会增加一个计数器,每当树莓派发送一个指令时,该计数器就会减少。为了向Arduino发送指令,这个计数器必须大于1。 在Python中,它通过信号量来实现。以下是该协议的C++绑定和Python绑定,其中包括了交互式命令解析器(在debug的时候会非常有用)。 图像处理部分
为了控制小车确保其能够沿着赛道前行,我们需要小车能够自行探测线路并能预测转弯,既能够在直线赛道全速行驶同时能够在转弯之前降低速度。上述功能我们通过对摄像头采集的图像进行处理分两步来实现完成,包括在获取探测线路后预测赛道曲率,以及检测确定赛道中心线。 预测赛道曲率 为了实现预测转弯并减少计算时间,我们通过摄像头对三个感兴趣区域点(ROI)进行探测捕捉,并对所捕获的图像进行了裁剪。然后,我们将一条线(上图1中的绿线)拟合到所获得的三个点上,并计算此线与参考线(上图1中的蓝线)之间的角度,从而估算出弯道的转弯程度。若此时是一条笔直赛道,则绿色与蓝线会重合。如上图1,右半图为三个感兴趣区域以及所预测的赛道中心(红色圆圈标出)。左半图为针对输入图像所计算出的结果 ,其中绿线为拟合线, 蓝线是对应于一条直线(直赛道)的参考线。 检测确定赛道中心 我们最初的检测方法是使用基于颜色的方法。 基本的想法是找到给定赛道颜色的最大区域,然后计算该区域的几何中心(即赛道中心)。 这里先对“颜色检测法”做一些简单介绍:首先在HSV颜色空间中转换图像,然后根据预定义的阈值计算颜色遮罩,最终所获得的几何中心即为赛道中心。上图2显示的是仿真环境下所获得的结果。 红圈表示找到的赛道中心,绿色线条对应于颜色遮罩的轮廓。现实中,只需要30行Python代码,就能够实现上述: 然而,这一方法最主要的缺点是在赛道不同区域环境光变化下所带来的检测不稳定性。我们尝试了直方图均衡法来克服这个问题,但发现效果并不理想,并且后者的计算量很大。 最后,我们决定将机器学习应用到这一项目中来检测赛道中心,即我们希望通过训练一个模型来从所获得的图像输入中预测出赛道中心的准确位置。我选择使用神经网络,因为这是我最熟悉的方法,并且使用纯粹的numpy和python代码其实很容易实现上述想法。 机器学习部分 “回归问题”概述 在监督式学习模式下,当我们标记数据时,我们的目标是预测所输入数据的标签(例如,预测图像中是否包含猫或狗)。 而在我们的这一项目中,我们想要预测来自摄像头所输入图像的赛道中心的坐标。为简化问题,针对所输入的图像区域,我们仅预测赛道中心的x坐标(沿着宽度),也就是说这里我们假定中心位于裁剪图像高度的一半处。 为了更好地评估我们的模型,我们选择均方误差(MSE)作为目标:我们取预测的x坐标与真正的赛道中心之间的平方误差,并在所有的训练样本上取平均值。 图像标记 在小车远程控制模式下录制赛道视频后,我们手动标记了3000张图像(在约25分钟内完成,即1张标签/秒)。为了达到目的,我们创建了自己的标记工具:每个训练图像逐一显示,对每一张图像我们点击白色赛道的中心,然后必须按任意键才能进入下一张图像。 预处理和数据增强 在将我们的学习算法应用到数据之前,我们先要完成以下几步:首先,我们需要调整所输入图像的大小以减小输入尺寸(减少4倍),从而大大减少学习参数的数量。这样可以简化问题,加快训练和预测时间。此外,为避免学习问题的产生并加快训练,需要对数据进行规范化。在我们的例子中,我们将输入图像统一在[-1,1]范围内,并将输出(赛道中心的预测x坐标)缩放为[0,1]。预处理脚本如下: 最后,为了增加训练样本的数量,我们将图像垂直翻转,以快速且简单的方式将训练集的大小乘以2。 神经网络架构 我们所使用的是一个前馈神经网络,由两个隐藏层组成,分别具有8个和4个单位。实际过程中,我们尝试了不同的架构,包括CNN(卷积神经网络),但我们发现前馈神经网络架构取得了最好的效果,可以以超过60 FPS的速度实时运行! 超参数的选择 我们选择的超参数包括网络架构,学习率,小批量大小...等。为了验证超参数的选择,我们将数据集分成3个子集:一个训练集(60%),一个验证集(20%)和一个测试集(20%)。 我们保持模型在验证集上的最低误差,并使用测试集估计我们的泛化误差。 ———————————————————————————— 最终,我们用了不到20分钟的时间,在8核笔记本电脑的CPU上对这一神经网络进行了训练。 训练数据包括7600+张标记的图片。下载后,会有两个文件夹,分别是: · input_images/ (小车远程控制模式下所获取的原始图像) · label_regions/ (输入图像的标记区域) 每张图片的命名规则为:“x_center"-"y_center"_"id".jpg,例如: · 0-28_452-453r0.jpg => center =(0, 28) | id = "452-453r0" · 6-22_691-23sept1506162644_2073r2.jpg=> center = (6, 22) | id = "691-23sept1506162644_2073r2" 小车循迹的控制 代码下载
|
|
相关推荐
|
|
608 浏览 0 评论
开源项目!基于Arduino做的“鱿鱼游戏”BOSS面具,支持动作检测
565 浏览 0 评论
用EDA做了一张校园卡但是发现学校大门刷不进去,学校内充当饭卡时能正常识别,不知道哪里出问题了
1292 浏览 2 评论
864 浏览 0 评论
781 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-6 09:20 , Processed in 0.912713 second(s), Total 62, Slave 43 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号