简介

EAIS-750E支持利用深度学习技术做音视频智能分析。

  • 搭载一颗5Tops算力的NPU,可以支持4路1080p H264视频流实时分析或等效100fps的图片分析。
  • 搭载4核2.2GHz Arm Cortex-A73 CPU和2核2.0GHz Arm Cortex-A53 CPU,可以支持ASR/TTS等实时音频分析处理。

EAIS-750E支持TengineOpenCV两种工具进行AI开发。

Tengine部署

image.png
Tengine规格与介绍参考Github项目。对于第一次使用Tengine的工程师,推荐开发流程如下:

熟悉Tengine API

利用EAIS-750E板载Tengine Example跑通一个模型,确认系统库正确性。例程下载地址,提取码750e。
$ cd /home/ubuntu/tengine_example
$ ./run.sh
正确运行结果如下

tengine-lite library version: 1.5-dev

model file : models/mobilenet_uint8.tmfile image file : images/cat.jpg img_h, img_w, scale[3], mean[3] : 224 224 , 0.017 0.017 0.017, 104.0 116.7 122.7

Repeat 1 times, thread 1, avg time 4.71 ms, max_time 4.71 ms, min_time 4.71 ms

5.520552, 283 5.200520, 285 5.040504, 281 4.880488, 282

4.720472, 287

进一步学习Tengine Example程序熟悉Tengine API调用方式和编写应用程序。

EAIS-750E本地编译Tengine

由于应用中除了AI推理之外,还往往包含视频解码/CV处理等依赖750E芯片加速库的环节,因此推荐采用750E上本地编译的方式编译应用程序。
其中Tengine库和头文件已经预装在系统中,版本为v1.5,路径如下,可以直接调用。

/usr/lib/libtengine-lite.so /home/ubuntu/tengine_example/include/tengine/

因为学习Tengine原理或升级功能,也可以参考教程2.6章节自行源码编译Tengine库,或参考下面简化教程

下载Tengine和TIM-VX代码仓库
$ git clone https://github.com/VeriSilicon/TIM-VX.git
$ git clone https://github.com/OAID/Tengine.git
$ cd Tengine
$ cp -rf ../TIM-VX/include ./source/device/tim-vx/
$ cp -rf ../TIM-VX/src ./source/device/tim-vx/
注,Tengine与TIM-VX会不断更新版本并且相互对应,如遇到最新版遇到问题,可以切到以下版本号:
Tengine v1.5: Tengine 75f83c6,TIM-VX 4f2991c
Tengine v1.4:Tengine lite-v1.4-amlogic,TIM-VX v1.1.32

编译Tengine
$ cd <tengine-lite-root-dir>
$ mkdir build && cd build
$ cmake .. -DTENGINE_ENABLE_TIM_VX=ON -DTENGINE_ENABLE_MODEL_CACHE=ON
$ make -jnproc&& make install
编译完成后,将build/install/lib/libtengine-lite.so 文件拷贝到/usr/lib/下替换原有库完成安装。

基于Tengine Model Zoo模型开发

Tengine Model Zoo已经适配了常见分类,目标检测,人脸关键点,骨骼关键点等模型。根据应用场景需求选取最接近应用需求的模型结构。参考对应模型的训练方法,用自己的数据训练模型。并用模型转换工具转成部署模型部署到EAIS-750E上。

部分模型性能数据

类型 框架 模型 Input_size(hwc) 耗时(ms)
分类网络 mxnet2onnx mobilenet 224x224x3 4.46
Resnet18 224x224x3 4.873
Resnet50 224x224x3 13.62
vgg16 224x224x3 17.89
检测网络 caffe MobileNet_SSD 300x300x3 21.09
pytorch2onnx NanoDet-m 320x320x3 12.4
darknet Yolov3 608x608x3 84
Yolov4-Tiny 416x416x3 13.58
pytorch2onnx yolov5n
yolov5s
yolov5m
yolov5l
640x640x3 46
72
125
197
人脸 mxnet2caffe RetinaFace 6409603 22.81
pytorch2onnx rfb 3203203 4.739
mxnet2caffe MobilefaceNet 1121123 12.93
文字识别 onnx OCR 322773 14.75

由于Tengine模型转换和量化工具只能在x86设备上运行,因此模型转换和量化步骤需要在x86 Host设备上完成。
Tengine社区提供了预编译模型转换和量化工具,如环境不匹配也可以通过Tengine项目源码编译生成(参考转换工具源码编译章节)。

Yolov5模型部署转换量化教程

下面以当前最流行的Yolov5模型为例详细介绍模型转换量化部署教程。由于Yolov5模型一直在更新,有多个历史版本,截止2022.5.14最新版本是v6.1,Tengine适配了v5.0和v6.0/6.1版本。本例采用的是Yolov5s模型v6.0版本(输入图像分辨率640x640),v6.1版本与v6.0版本操作完全相同,v5.0版本流程类似,略做修改即可。整个流程包括:

模型训练导出简化 -> 转成tmfile模型并仿真 -> tmfile模型量化 -> 模型部署测试

其中前三步都在x86 Host机上完成,最后一步模型部署测试在EAIS-750E上完成。整个过程x86 Host机和750E上都要下载编译Tengine。
x86 Host机系统推荐使用Ubuntu20.04,如用ubuntu18.04系统,会需要升级cmake,protobuf,python等一系列工具版本。EAIS-750E上已经预装Ubuntu18.04系统并升级完所有组件。

a,模型训练导出简化

模型训练参照Yolov5项目官方教程。
导出程onnx模型,参照官方教程,博主实验简化教程如下
$ git clone https://github.com/ultralytics/yolov5
$ cd yolov5
$ git checkout v6.0
$ pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
$ pip3 install onnx onnx-simpilier onnxruntime -i https://pypi.tuna.tsinghua.edu.cn/simple

下载预训练yolov5s pt文件或保存自己训练的pt文件到 yolov5/weights/
$ mkdir weights
$ python3 export.py --weights weights/yolov5s.pt --opset 10 --simplify --train
tmfile转换要求opset要指定为10,—train是为了去掉后处理

运行成功结果如下:

export: data=data/coco128.yaml, weights=weights/yolov5s.pt, imgsz=[640, 640], batch_size=1, device=cpu, half=False, inplace=False, train=True, optimize=False, int8=False, dynamic=False, simplify=True, opset=10, topk_per_class=100, topk_all=100, iou_thres=0.45, conf_thres=0.25, include=[‘torchscript’, ‘onnx’] YOLOv5 🚀 v6.0-0-g956be8e torch 1.11.0+cu102 CPU

Fusing layers… Model Summary: 213 layers, 7225885 parameters, 0 gradients, 16.5 GFLOPs

PyTorch: starting from weights/yolov5s.pt (14.8 MB)

TorchScript: starting export with torch 1.11.0+cu102… TorchScript: export success, saved as weights/yolov5s.torchscript.pt (29.2 MB)

ONNX: starting export with onnx 1.11.0… ONNX: simplifying with onnx-simplifier 0.3.10… ONNX: export success, saved as weights/yolov5s.onnx (28.9 MB) ONNX: run —dynamic ONNX model inference with: ‘python detect.py —weights weights/yolov5s.onnx’

Export complete (5.02s) Results saved to /home/william/yolov5/weights

转换成功后,把生成的yolov5s.onnx模型copy到Tengine/models/。
$ cp weights/yolov5s.onnx ../Tengine/models/

Yolov5s onnx模型的Swich OP是用小算子拼起来的对NPU不友好,Focus和后处理也需要切掉用CPU处理(参考知乎介绍)。借助Tengine项目提供的yolov5s-opt.py脚本简化模型
$ git clone https://github.com/oaid/Tengine.git
$ cd Tengine/
$ python3 ./tools/optimize/yolov5s-opt.py \
$ --input models/yolov5s.onnx --output models/yolov5s_v6_opt.onnx \
$ --in_tensor images --out_tensor output,351,365 --cut_focus
其中in_tensor为onnx模型的第一个concat的outputs或images,out_tensor为几个transpose的outputs,yolov5n和yolov5s的节点号相同,yolov5m和yolov5l的节点号需要自行用netron打开网络拓扑查看。
—cut_focus表示不处理focus,v6.0/6.1模型没有focus结构要添加该选项,v5.0模型有focus结构无需该选项。

执行结果在Tengine/models/目录下生成简化过的yolov5s_v6_opt.onnx模型,输出如下

—— Tengine YOLOv5 Optimize Tool ——

Input model : models/yolov5s.onnx Output model : models/yolov5s_v6_opt.onnx Input tensor : images Output tensor : output,351,365 [Quant Tools Info]: Step 0, load original onnx model from models/yolov5s.onnx. 202 [Quant Tools Info]: Step 1, Remove the focus and postprocess nodes. [Quant Tools Info]: Step 2, Using hardswish replace the sigmoid and mul. [Quant Tools Info]: Step 3, Rebuild onnx graph nodes. [Quant Tools Info]: Step 4, Update input and output tensor. [Quant Tools Info]: Step 5, save the new onnx model to models/yolov5s_v6_opt.onnx.

—— Tengine YOLOv5s Optimize onnx create success, best wish for your inference has a high accuracy …(^0^)/ ——

b, 转成tmfile模型并仿真

用Tengine提供的convert tools将yolov5s的onnx模型转换成tmfile模型,并利用Tengine在x86 Host机上仿真,看推理结果是否正确。convert tools在Tengine工程里打开选项编译得到。编译convert tools时顺便把量化工具quant_tool也一起编译了,编译会依赖OpenCV、protobuf等依赖库,先预先安装好
$ sudo apt install libprotobuf-dev protobuf-compiler libopencv-dev
正式编译命令如下:
$ cd <tengine-lite-root-dir>
$ mkdir build && cd build
$ cmake .. -DTENGINE_BUILD_CONVERT_TOOL=ON -DTENGINE_BUILD_QUANT_TOOL=ON
$ make && make install
编译成功后,Tengine/build/install/bin/ 有convert_tool,quant_tool_uint8等工具以及tm_yolov5s测试程序。
convert_tools与quant_tools的使用手册见Tengine使用文档。利用convert_tool转换onnx模型为tmfile浮点模型并保存在Tengine/models/。
$ cd <tengine-lite-root-dir>
$ ./build/install/bin/convert_tool -f onnx \
$ -m ./models/yolov5s_v6_opt.onnx \
$ -o ./models/yolov5s.tmfile
转换成功显示输出如下

—— Tengine Convert Tool ——

Version : v1.0, 23:08:32 May 17 2022 Status : float32

—————onnx2tengine begin————— Model op set is: 10 Internal optimize in onnx serializer done. —————onnx2tengine done.————— graph opt begin graph opt done. Convert model success. ./models/yolov5s_v6_opt.onnx ——-> ./models/yolov5s.tmfile

利用Tengine项目提供的yolov5s例程来测试下转换的tmfile模型是否正确。注意,tm_yolov5s.cpp源文件中的宏YOLOV5_VERSION6 ,该宏打开对应v6.0版本的yolov5s模型(没有focus结构),该宏关闭对应v5.0版本的yolovs模型(有focus结构)。我们测试v6.0版本yolov5s模型,所以要确保打开宏编译tm_yolov5s测试程序。

define YOLOV5_VERSION6 1

测试图片可以保存下图命名为ssd_dog.jpg或测试图片到Tengine/images/ 路径下
image.png
$ cd <tengine-lite-root-dir>
$ export LD_LIBRARY_PATH=./build/install/lib
$ ./build/install/bin/tm_yolov5s -m models/yolov5s.tmfile -i images/ssd_dog.jpg
正确执行结果如下:

tengine-lite library version: 1.5-dev

Repeat 1 times, thread 1, avg time 531.80 ms, max_time 531.80 ms, min_time 531.80 ms

detection num: 6 16: 92%, [ 138, 223, 307, 541], dog 2: 77%, [ 473, 80, 686, 172], car 1: 58%, [ 181, 104, 572, 426], bicycle 1: 55%, [ 128, 142, 262, 377], bicycle 62: 53%, [ 4, 0, 78, 244], tv 58: 33%, [ 681, 110, 716, 156], potted plant

注意,仿真测试时有可能会遇到推理结果与训练结果偏差过大的问题,大概率是a步骤中yolov5s-opt.py优化模型时替换HardSwish算子引入的,验证和解决方法是注释跳过脚本里的HardSwish替换步骤,也可以自己训练模型用relu替换yolov5的hardswish算子构建和训练模型。

c,模型量化

EAIS-750E上的Amlogic A311D的NPU支持perlayer的uint8量化格式,因此借助tengine提供的quant_tool_uint8工具进行量化,使用方法参考量化使用说明。量化时需要从模型测试数据集中挑选500-1000张图片用于量化校准,放在Tengine/dataset/下,博主用官方预训练模型用的coco数据集中挑选了500张图片。
$ cd <tengine-lite-root-dir>
$ ./build/tools/quantize/quant_tool_uint8 -m ./models/yolov5s.tmfile \
$ -i ./dataset/ -o ./models/yolov5s_uint8.tmfile \
$ -g 3,640,640 -w 104,117,123 -s 0.017,0.017,0.017
量化时输入与训练匹配的尺寸,mean,scale参数。

执行结果如下:

—— Tengine Post Training Quantization Tool ——

Version : v1.2, 23:08:28 May 17 2022 Status : uint8, per-layer, asymmetric Input model : ./models/yolov5s.tmfile Output model: ./models/yolov5s_uint8.tmfile Calib images: ./dataset/ Scale file : NULL Algorithm : 0 Dims : 3 640 640 Mean : 104.000 117.000 123.000 Scale : 0.017 0.017 0.017 BGR2RGB : ON Center crop : OFF Letter box : 0 0 YOLOv5 focus: OFF Thread num : 4

[Quant Tools Info]: Step 0, load FP32 tmfile. [Quant Tools Info]: Step 0, load FP32 tmfile done. [Quant Tools Info]: Step 0, load calibration image files. [Quant Tools Info]: Step 0, load calibration image files done, image num is 448. [Quant Tools Info]: Step 1, find original calibration table. [Quant Tools Info]: Step 1, images 00448 / 00448 [Quant Tools Info]: Step 2, find original calibration table done, output ./table_minmax.scale [Quant Tools Info]: Thread 4, image nums 448, total time 145428.19 ms, avg time 324.62 ms [Quant Tools Info]: Step 3, load FP32 tmfile once again [Quant Tools Info]: Step 3, load FP32 tmfile once again done. [Quant Tools Info]: Step 3, load calibration table file table_minmax.scale. [Quant Tools Info]: Step 4, optimize the calibration table. [Quant Tools Info]: Step 4, quantize activation tensor done. [Quant Tools Info]: Step 5, quantize weight tensor done. [Quant Tools Info]: Step 6, save UInt8 tmfile done, ./models/yolov5s_uint8.tmfile

—— Tengine Int8 tmfile create success, best wish for your UInt8 inference has a low accuracy loss…(^0^)/ ——

把量化生成的yolov5s_uint8.tmfile和测试用的ssd_dog.jpg图片拷贝到750E设备上备用
$ scp Tengine/images/ssd_dog.jpg ubuntu@192.168.xx.xx:/home/ubuntu/Tengine/images/
$ scp Tengine/models/yolov5s_uint8.tmfile ubuntu@192.168.xx.xx:/home/ubuntu/Tengine/models/

d,模型部署测试

Tengine项目example里提供的tm_yolov5s_timvx应用来测试模型部署。该应用需要在750E上编译Tengine Example应用得到。参考第一步教程,在750E上下载Tengine项目并编译,同样注意,编译时需要确保tm_yolov5s_timvx.cpp里的宏YOLOV5_VERSION6打开。
$ cd <tengine-lite-root-dir>
$ export LD_LIBRARY_PATH=./build/install/lib
$ ./build/install/bin/tm_yolov5s_timvx -m models/yolov5s_uint8.tmfile -i images/ssd_dog.jpg

成功运行结果输出如下:

tengine-lite library version: 1.5-dev

Repeat 1 times, thread 1, avg time 73.35 ms, max_time 73.35 ms, min_time 73.35 ms

detection num: 9 2: 93%, [ 474, 77, 681, 170], car 16: 91%, [ 134, 213, 308, 546], dog 62: 73%, [ 0, 0, 78, 250], tv 1: 62%, [ 190, 111, 574, 421], bicycle 1: 48%, [ 126, 143, 262, 381], bicycle 14: 43%, [ 59, 63, 115, 127], bird 62: 42%, [ 718, 0, 766, 272], tv 1: 40%, [ 143, 140, 257, 226], bicycle 0: 29%, [ 688, 12, 765, 575], person

量化结果与浮点结果会略有差异,这是量化造成的精度误差。
如果误差过大影响应用,那就需要重新量化调试甚至重新训练模型。

自研模型开发部署(进阶需求)

对于希望使用自研算法的高级开发者,请参照学习Tengine Github项目中的资源。
在x86设备Host设备上基于Tengine TIM-VX上支持的算子列表搭建模型结构和训练模型,并转换和量化模型。
最后参考Tengine Example代码部署到EAIS-750E上。

中间有可能遇到模型转换错误,请求助开源社区QQ群829565581 获得支持。

OpenCV部署

image.png

2022年4月,OpenCV也支持通过TIM-VX后端调用NPU了。EAIS-750E已经完美支持TIM-VX驱动,因此也支持OpenCV调用NPU推理。OpenCV是图片处理的必用工具,使用OpenCV做AI推理的优势是在一套框架下完整完成图像处理和AI推理流程简化系统设计,并且OpenCV采用int8量化方式,感兴趣的人也可以尝试。

经过测试,EAIS-750E可以完整运行OpenCV_zoo提供的所有案例demo。本教程基于官方部署教程针对EAIS-750E系统环境修改得到,已投稿OpenCV官方被接受。

源码编译安装OpenCV-python

EAIS-750E上已经预装了VIVANTE SDK和cmake等工,简化安装教程如下:
先安装工具python3、python3-numpy、git-lfs工具,卸载系统预装的OpenCV3.2以免系统库版本混乱
$ sudo apt install python3 python3-dev python3-numpy git-lfs
$ sudo apt autoremove libopencv-dev

下载opencv源代码并编译,安装路径/usr/local/,打开TIMVX后端,打开python接口,关闭TEST节省编译时间
$ git clone https://github.com/opencv/opencv
$ cd opencv && mkdir build && cd build
$ cmake .. -D WITH_TIMVX=ON -D CMAKE_BUILD_TYPE=RELEASE \
-D BUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF \
-D CMAKE_INSTALL_PREFIX=/usr/local/ \
-D PYTHON3_INCLUDE_DIR=/usr/include/python3.6 \
-D PYTHON3_EXECUTABLE=/usr/bin/python3.6 \
-D PYTHON3_LIBRARY=/usr/lib/aarch64-linux-gnu/
$ make -j 6
$ sudo make install
$ sudo cp /usr/local/lib/python3.6/site-packages/cv2/python-3.6/cv2.cpython-36m-aarch64-linux-gnu.so /usr/local/lib/python3.6/dist-packages/cv2.so

6线程编译可大幅度缩短编译时间,大约需要30min。安装成功后python能够找到cv2组件
$ python3 -c "import cv2; print(cv2.__version__)"

ubuntu@750E:~$ python3 -c “import cv2; print(cv2.version)” 4.6.0-pre

模型性能测试

借助OpenCV提供的Model Zoo benchmark测试性能,使用方法参考OpenCV zoo benchmark教程
首先下载opencv zoo项目并下载model。model有742MB有点大,下载需要20min左右。
$ git clone https://github.com/opencv/opencv_zoo && cd opencv_zoo
$ git lfs install && git lfs pull

下载模型的同时另开一个终端安装依赖库,numpy安装大约也要20min。
$ sudo apt install python3-pip
$ pip3 install Cython pyyaml -i https://pypi.tuna.tsinghua.edu.cn/simple
$ pip3 install numpy requests -i https://pypi.tuna.tsinghua.edu.cn/simple
注意,不要用官方教程中requirements.txt来安装依赖库,因为流程里包含安装opencv-python库,此库不支持TIMVX后端并且是单线程源码编译会持续2小时,并且会覆盖之前编译的opencv-python库。

下载测试需要的图片文件,百度网盘地址 (code: pvrw),全部下载下来放到opencv_zoo/benchmark/data目录下解压。

benchmark依赖yaml文件,修改config下的yaml文件,以face_detection_yunet为例
$ cd benchmark
$ vim config/face_detection_yunet.yaml

  • backend: “default” -> “timvx”
  • target: “cpu” -> “npu”
  • warm和repeat都设成1次,因为NPU第1次运行编译耗时很长,之后执行1次和10次耗时是一致的
  • modelPath 更换成路径下的int8模型,否则用浮点模型会fallback到CPU执行

    Benchmark: name:”Face Detection Benchmark” type:”Detection” data: path:”benchmark/data/face_detection” files:[“group.jpg”, “concerts.jpg”, “dance.jpg”] sizes: # [[w1, h1], …], Omit to run at original scale

    1. - [160, 120]
    2. - [640, 480]

    metric: warmup:1 repeat:1 reduction:”median” backend:”timvx target:”npu

    Model: name:”YuNet” modelPath:”models/face_detection_yunet/face_detection_yunet_2022mar-act_int8-wt_int8-quantized.onnx” confThreshold:0.6 nmsThreshold:0.3 topK:5000

修改yaml文件后就可以运行测试了
$ cd benchmark
$ PYTHONPATH=.. python3 benchmark.py --cfg ./config/face_detection_yunet.yaml

Benchmarking YuNet: image: group.jpg [160, 120], latency (median): 4.2197 ms [640, 480], latency (median): 193.7665 ms image: concerts.jpg [160, 120], latency (median): 4.2404 ms [640, 480], latency (median): 38.0642 ms image: dance.jpg [160, 120], latency (median): 4.3989 ms [640, 480], latency (median): 38.4221 ms

于老师开发的世界上最快的人脸检测模型YuNet只需要4.2ms,Nice!

经过实际测试,EIAS-750E 运行OpenCV_zoo的性能benchmark数据表格如下

Model Input Size RPI-CPU (ms) 750E-CPU (ms) JETSON-GPU (ms) KV3-NPU (ms) 750E-NPU (ms)
YuNet 160x120 6.22 5.99 12.18 4.04 4.2
SFace 112x112 99.20 85.7 24.88 46.25 52
DB-IC15 640x480 2835.91 2064 208.41 —- —-
DB-TD500 640x480 2841.71 2047 210.51 —- —-
CRNN-EN 100x32 234.32 237.4 196.15 125.30 158
CRNN-CN 100x32 322.16 310.5 239.76 166.79 210
PP-ResNet 224x224 602.58 541 98.64 75.45 67.7
MobileNet-V1 224x224 92.25 86.1 33.18 145.66* 150.9*
MobileNet-V2 224x224 74.03 31.92 146.31* 148.5*
PP-HumanSeg 192x192 105.32 92.2 67.97 74.77 36.2
WeChatQRCode 100x100 37.68 —- —- —-
DaSiamRPN 1280x720 705.48 574.8 76.82 —- —-
YoutuReID 128x256 521.98 502.7 90.07 44.61 45.5
MPPalmDet 256x256 89.41 165 50.64 145.56* 313.5*

从上表中看到,
EAIS-750E CPU性能与树莓派4接近并略强一些,因为750E有4个A73 CPU主频达2.2GHz比树莓派1.5GHz强不少。
EAIS-750E NPU性能与同样搭载A311D芯片的Khadas VIM3基本一致,个别模型细微差异因为两块板子的NPU驱动版本和DDR内存规格不同。mobilenetv1/v2/MPPalmDet模型耗时特别长,是因为OpenCV_zoo提供的是perchannel量化的模型,A311D上的NPU只支持pertensor量化算子,不支持perchannel量化算子高性能计算。