- 题目选择
车辆在无驾驶员操作的情况下自行实现驾驶,需要通过传感器实时感知到车辆及周边环境的情况,再通过智能系统进行规划决策,最后通过控制系统执行驾驶操作。识别交通标志就是其中一个基本功能。
刚好硬禾与ADI联合举办了基于MAX78000的智能边缘应用设计大赛,在自动驾驶大热的今天,我们也蹭蹭热点吧。MAX78000FTHR为快速开发平台,帮助工程师利用MAX78000 Arm® Cortex® M4F处理器快速实施超低功耗、人工智能(AI)方案,器件集成卷积神经网络加速器。
- 搭建环境
首先安装了MAX78000的开发包,顺手跑了个hello world。
嗯,红绿LED一切正常。
然后也再去搭建训练环境。方便起见,我选择了在win10上安装WSL。同时为了方便管理python环境,我们并没有完全按照readme建议的做法,而是用安装了anaconda之后,利用conda来创建新的python3.8.11环境,并且根据ai8x-training和ai8x-synthesis中requirements.txt的要求安装pytorch等开发包,同时满足训练和合成的要求。
- 收集数据
为了能够尽快完成最小可行产品,我们利用公开数据库,从http://www.nlpr.ia.ac.cn/pal/trafficdata/recognition.html下载了中国交通标志检测数据集(CCTSDB)。TSRD包括6164个交通标志图像,包含58个标志类别。图像分为训练数据库和测试数据库两个子数据库。训练数据库包含4170张图像,而测试数据库包含1994张图像。所有图像都标注了符号和类别的四个坐标。
考虑到MAX78000自带摄像头采集到的图像与TSRD数据存在差异,为了尽可能提高模型准确度,如果有时间我们会用MAX78000补充拍摄一些图像。
另外,考虑到MAX78000性能有限,在这次演示中我们把数据简单分成允许和禁止两种。如下图所示
- 允许
- 禁止
整理好的数据集放在目录ai8x-training\data\TrafficSigns\下
- 训练模型
我们采用了例子cat_vs_dog中的网络模型。这是一个七层的神经网络,在大模型泛滥的今天,这个还真是TinyML了。
// Input data: HWC
// Layer 0: 3x128x128 streaming, no pooling, conv2d with kernel size 3x3, stride 1/1, pad 1/1, ReLU, 16x128x128 output
// Layer 1: 16x128x128 streaming, max pool 2x2 with stride 2/2, conv2d with kernel size 3x3, stride 1/1, pad 1/1, ReLU, 32x64x64 output
// Layer 2: 32x64x64, max pool 2x2 with stride 2/2, conv2d with kernel size 3x3, stride 1/1, pad 1/1, ReLU, 64x32x32 output
// Layer 3: 64x32x32, max pool 2x2 with stride 2/2, conv2d with kernel size 3x3, stride 1/1, pad 1/1, ReLU, 32x16x16 output
// Layer 4: 32x16x16, max pool 2x2 with stride 2/2, conv2d with kernel size 3x3, stride 1/1, pad 1/1, ReLU, 32x8x8 output
// Layer 5: 32x8x8, no pooling, conv2d with kernel size 3x3, stride 1/1, pad 1/1, ReLU, 16x8x8 output
// Layer 6: 16x8x8 flattened to 1024x1x1, no pooling, linear, no activation, 2x1x1 output
几个epoch之后,训练就很快收敛了
跟着我们参考说明文档,对训练好的神经网络模型进行量化等操作,最后生成C++代码。
- 芯片部署
在Maxim集成开发环境中,我们参考cat_vs_dog的例子创建了项目。
然后把训练、量化后得到的c++文件拷贝到新创建的项目中,覆盖掉原来的代码
cnn.c / cnn.h / sampledata.h / sampleoutput.h / softmax.c / weights.h
- 测试结果
我们准备了一些图片进行测试。
- 允许
- 禁止
从结果看来还是很准确的