1 目标
之前已经熟悉了树莓派系统、Python语言和OpenCV库,而且组装了自己的玩具小车,我想结合OpenCV机器视觉算法和小车做一个小项目,因为我桌上有个网球,所以就想到实现小车通过机器视觉跟踪网球的功能,大概效果就是小车可以通过摄像头检测到是否存在网球,如果存在就跟踪网球,这里所谓的让小车跟踪网球,指的是让小车始终正对网球并保持一定距离。
2 前期准备
要实现这个目标,花费了我近两个月的时间,主要是要花时间去了解相关的机器视觉算法和熟悉OpenCV的使用,主流的图像处理和机器学习算法在OpenCV中都有现成的接口可以调用,因此对于应用者来说,虽然需要了解这些算法,但不需要太深入,知道这些算法的意义、可以灵活运用就可以了。我参考的书是《OpenCV3计算机视觉 Python语言实现(原书第2版)》,这本书很薄,想从这本书上深入学习相关算法是不可能的,但可以把它当成路线指导,自己去搜索资料来配合阅读。
在正式编写程序之前,我总结出下面这些要事先准备的东西:
①熟悉树莓派操作系统Raspbian,熟悉Python的语法,熟悉用ssh远程访问树莓派和传输文件;
②OpenCV的安装和使用。在树莓派上的OpenCV安装可参考这篇文章:https://www.cnblogs.com/zjutlitao/archive/2018/01/12/8261688.html,这篇博文中是使用了Python虚拟环境在Python3中使用OpenCV,其实如果不用Python虚拟环境的话直接编译OpenCV源码也是可以的,只不过可能只能用Python2调用OpenCV了。至于OpenCV的使用,关键是要熟悉OpenCV下文件IO、图像格式转换、捕获摄像头和窗口显示等操作,另外也需要熟悉OpenCV依赖的numpy模块的使用。
③了解相关图像算法。关键词:色彩空间;图像特征;目标检测、分类器、Haar级联;目标跟踪、均值漂移、CAMShift。
④UDP传输视频帧,这是为了可以实时查看图像情况,具体内容见之前的文章。
⑤树莓派GPIO的控制,这是为了控制电机,具体内容见之前的文章。
当然,事先得组装好小车,并配有一个USB摄像头(我的是罗技C270i),其实物图如下图所示。
3 算法流程
整个程序就是几种机器视觉算法的综合运用,总体的算法流程如下图所示:
这里涉及到的算法要从复杂的数学公式中理解原理还是相当有难度的,我在翻阅资料时基本是跳过了里面的数学验证,只是大概了解原理和步骤。
OpenCV中可以使用CascadeClassifier对象进行尺度不变的Haar级联分类或跟踪,Haar级联器在人脸检测中是最常用的,不过我们可以通过训练自己的分类器来检测特定物品。调用CascadeClassifier对象的detectMultiScale方法就可以检测图像中的目标了,使用起来只是几行代码的事,不过其原理涉及到特征提取、滑动窗口、分类器和非最大抑制等多个概念。
理论上,只用Haar级联检测就可以实现目标跟踪了,即对每一帧图像进行Haar级联检测,不过实际应用起来有两点需要考虑:
1、Haar级联检测计算量比较大,如果是在PC上倒还感觉不到慢,但在树莓派上运行就有些吃力了,对每一帧都进行这么大的计算,就会显得非常卡;
2、Haar级联检测并不能保证一定能检测到目标,以我要检测的网球为例,虽然网球的造型已经是比较简单了,但是它的各个面看起来都是有些差异的,而且有的面上还有文字,要使自己训练的分类器能几乎完全识别网球的各个面,就必须对网球的各个面采集样本图像,这个工作量太大了。
考虑到这些,在检测到网球后,使用CAMShift来对网球目标进行跟踪。CAMShift是均值漂移MeanShift的改进算法,其改进之处主要在于可以自动调节跟踪窗口的尺寸。均值漂移的基本思想是通过迭代寻找概率函数离散样本的最大密度,其最大的优点就是计算速度快,当然它的缺点主要是比较依赖目标的颜色特征,不过好在网球的颜色是比较独特和单一的。
用CAMShift可以得到包含目标的矩形框,计算矩形框的中心点,将其和屏幕中心比较,判断小车应该左转还是右转;计算矩形框的尺寸,将其和设定的值进行比较,判断小车应该前进还是后退。
4 分类器训练
为了使用Haar级联器检测网球,需要自己手动采集素材并训练模型,这个过程其实是最耗时的。训练方法可以参考这篇博文http://blog.topspeedsnail.com/archives/10511,或者是OpenCV的官方说明https://docs.opencv.org/2.4.13/doc/user_guide/ug_traincascade.html?highlight=opencv_createsamples。
首先采集大量的负样本图片,一般要大于1000,而且负样本最好是在要测试的场地采集。下面这些图是我采集的负样本图像,都是从我所在的办公室采集的。首先采集大量的负样本图片,一般要大于1000,而且负样本最好是在要测试的场地采集。下面这些图是我采集的负样本图像,都是从我所在的办公室采集的。(可以在小车上写个程序,让小车自动采集周围的图片)