简介
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支持Tengine和OpenCV两种工具进行AI开发。
Tengine部署
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 -j
nproc&& 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/ 路径下$ 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部署
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
- [160, 120]
- [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量化算子高性能计算。