灵眸边缘计算产品学习

EASY EAI灵眸科技 | 让边缘AI落地更简单 (easy-eai.com)

产品简介

支持4路1080P@30fps视频流采集,四核CPU@1.5GHz与2Tops AI边缘算力能力。集成有以太网、Wi-Fi、4G等网络通信外设;RS232、RS485、UART等本地通信接口。HDMI显示屏接口、音频输入输出等交互外设。2路USB Host接口、2路Type-C调试接口。继电器、指示灯、TF卡、按键等通用外设。可内置人员闯入识别、人数检测、火焰检测、安全帽识别、聚众识别等各类AI算法,并支持ubuntu系统供客户二次开发

实物接线

入门指南

电源

编译环境

产品调试方式

ADB

串口

网络

开发方式

交叉编译

优点:

       采用x86架构的CPU进行编译,编译速度快。

       源码编辑方便,开发环境支持各种如vsCode、qtCreator等IDE。

缺点:

       编译环境需要进行安装部署。

       程序的调试运行操作相对本地编译不那么直接。

固件烧录

异常情况直接查文档

AI算法组件

AI算法开发流程

模型转换工具搭建

 执行以下指令加载模型转换工具docker镜像:

docker load --input /home/developer/rknn-toolkit/rknn-toolkit-1.7.3-docker.tar.gz

执行以下指令进入镜像bash环境:

docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb rknn-toolkit:1.7.3 /bin/bash

 输入“python”加载python相关库,尝试加载rknn库,如下图环境测试成功:

模型转换示例

执行以下指令把工作区域映射进docker镜像,其中/home/developer/rknn-toolkit/model_convert为工作区域,/test为映射到docker镜像,/dev/bus/usb:/dev/bus/usb为映射usb到docker镜像:

docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb -v /home/developer/rknn-toolkit/model_convert:/test rknn-toolkit:1.7.3 /bin/bash

在docker环境切换到模型转换工作目录:

cd /test/coco_object_detect/

执行gen_list.py生成量化图片列表:

python gen_list.py

生成“量化图片列表”如下文件夹所示:

在执行rknn_convert.py脚本进行模型转换:

python rknn_convert.py

 生成模型如下图所示,此模型可以在rknn环境和EAI-BOX1000环境运行:

yolov5_coco_test.py脚本在PC端的环境下可以运行rknn的模型

执行yolov5_coco_test.py脚本测试rknn模型:

python yolov5_coco_test.py

 由于rknn模型用NPU API在EAI-BOX1000加载的时候启动速度会好慢,在评估完模型精度没问题的情况下,建议进行模型预编译。预编译的时候需要通过EAI-BOX1000主板的环境,所以请务必接上adb口与ubuntu保证稳定连接。

虚拟机要保证接上adb设备:

由于在虚拟机里ubuntu环境与docker环境对adb设备资源是竞争关系,所以需要关掉ubuntu环境下的adb服务,且在docker里面通过apt-get安装adb软件包。以下指令在ubuntu环境与docker环境里各自执行:

在docker环境里执行adb devices,现象如下图所示则设备连接成功:

运行precompile_rknn.py脚本把模型执行预编译:

python precompile_rknn.py

至此预编译部署完成,模型转换步骤已全部完成。生成如下预编译后的int8量化模型:

模型转换API

RKNN 模型配置
APIconfig
描述设置模型参数
参数batch_size:批处理大小,默认值为 100。量化时将根据该参数决定每一批次参与运算的数据量,以校正量化结果。如果dataset中的数据量小于batch_size,则该参数值将自动调整为dataset中的数据量。如果量化时出现内存不足的问题,建议将这个值设小一点,例如 8。
mean_values:输入的均值。该参数与 channel_mean_value参数不能同时设置。参数格式是一个列表,列表中包含一个或多个均值子列表,多输入模型对应多个子列表,每个子列表的长度与该输入的通道数一致,例如[[128,128,128]],表示一个输入的三个通道的值减去128。如果 reorder_channel设置成’2 1 0‘,则优先做通道调整,再做减均值。
std_values:输入的归一化值。该参数与channel_mean_value参数不能同时设置。参数格式是一个列表,列表中包含一个或多个归一化值子列表,多输入模型对应多个子列表,每个子列表的长度与该输入的通道数一致,例如[[128,128,128]],表示设置一个输入的三个通道的值减去均值后再除以128。如果 reorder_channel设置成’2 1 0‘,则优先做通道调整,再减均值和除以归一化值。
epochs:量化时的迭代次数,每迭代一次,就选择 batch_size 指定数量的图片进行量化校正。默认值为-1,此时 RKNN-Toolkit 会根据dataset中的图片数量自动计算迭代次数以最大化利用数据集中的数据。
reorder_channel:表示是否需要对图像通道顺序进行调整,只对三通道输入有效。’0 1 2’表示按照输入的通道顺序来推理,比如图片输入时是 RGB,那推理的时候就根据 RGB顺序传给输入层;’2 1 0’表示会对输入做通道转换,比如输入时通道顺序是RGB,推理时会将其转成 BGR,再传给输入层,同样的,输入时通道的顺序为 BGR 的话,会被转成 RGB 后再传给输入层。如果有多个输入,每个输入的参数以“#”进行分 隔,如 ’0 1 2#0 1 2’。该参数的默认值是 None,对于 Caffe 框架的三通道输入模型,表示需要做通道顺序的调整,其他框架的三通道输入模型,默认不做通道顺序调整。
need_horizontal_merge:是否需要进行水平合并,默认值为 False。如果模型是 inception v1/v3/v4,建议开启该选项,可以提高推理时的性能。
quantized_dtype:量化类型,目前支持的量化类型有 asymmetric_quantized-u8、dynamic_fixed_point-i8、dynamic_fixed_point-i16,默认值为 asymmetric_quantized-u8。
quantized_algorithm: 量化参数优化算法。当前版本支持的算法有:normal,mmse和kl_divergence,默认值为normal。其中normal 算法的特点是速度较快。而mmse算 法,因为需要对量化参数进行多次调整,其速度会慢很多,但通常能得到比normal算法更高的精度;kl_divergence所用时间会比 normal多一些,但比 mmse 会少很多,在某些场景下可以得到较好的改善效果。
mmse_epoch:mmse量化算法的迭代次数,默认值为 3。通常情况下,迭代次数越多,精度往往越高。
optimization_level:模型优化等级。通过修改模型优化等级,可以关掉部分或全部模型转换过程中使用到的优化规则。该参数的默认值为 3,打开所有优化选项。值为2或1时关闭一部分可能会对部分模型精度产生影响的优化选项,值为0时关闭所有 优化选项。
target_platform:指定RKNN模型目标运行平台。目前支持RK1806、RK1808、RK3399Pro、RV1109和RV1126。其中基于RK1806、RK1808 或 RK3399Pro生成的RKNN模型可以在这三个平台上通用,基于 RV1109或RV1126生成的RKNN模型可以在这两个平台通用。如果模型要在RK1806、RK1808或RK3399Pro上运行,该参数的值可以是 [“rk1806”], [“rk1808”], [“rk3399pro”]或 [“rk1806”, “rk1808”, “rk3399pro”]等;如果模型要在RV1109 或 RV1126 上运行,该参数的值可以是 [“rv1126”], [“rv1109”]或[“rv1109”, “rv1126”]等。这个参数的值不可以是类似[“rk1808”, “rv1126”]这样的组合,因为这两款芯片互不兼容。如果不填该参数,则默认是 [“rk1808”],生成的RKNN 模型可以在 RK1806、RK1808和RK3399Pro 平台上运行。 该参数的值大小写不敏感。
quantize_input_node: 开启后无论模型是否量化,均强制对模型的输入节点进行量化。 输入节点被量化的模型,在部署时会有性能优势,rknn_input_set接口的耗时更少。当 RKNN-Toolkit 量化没有按理想情况对输入节点进行量化(仅支持输入为图片的模型)、或用户选择加载深度学习框架已生成的量化模型时可以启用(这种情况下,第一层的quantize_layer会被合并到输入节点)。默认值为 False。
merge_dequant_layer_and_output_node: 将模型输出节点与上一层的dequantize_layer,合并成一个被量化的输出节点,允许模型在部署时返回 uint8或 float类型的推理结果。此配置仅对加载深度学习框架已生成的量化模型有效。默认为 False。
返回值

模型加载
ONNX 模型加载
APIload_onnx
描述加载ONNX模型
参数model:ONNX模型文件(.onnx 后缀)所在路径。
inputs:指定模型的输入节点,数据类型为列表。例如示例中的 resnet50v2模型,其输入节点是['data']。默认值是 None,此时工具自动从模型中查找输入节点。可选参数。
input_size_list:每个输入节点对应的数据形状。例如示例中的 resnet50v2模型,其输入节点对应的输入尺寸是[[3, 224, 224]]。可选参数。
注:1. 填写输入数据形状时不要填 batch 维。如果要批量推理,请使用 build 接口的             rknn_batch_size 参数。
       2. 如果指定了 inputs 节点,则该参数必须填写。
outputs:指定模型的输出节点,数据类型为列表。例如示例中的 resnet50v2模型,其 输出节点是['resnetv24_dense0_fwd']。默认值是 None,此时工具将自动从模型中搜索输出节点。可选参数。
返回值0:导入成功
-1:导入失败
 PyTorch 模型加载接口
APIload_pytorch
描述加载 PyTorch模型
参数model:PyTorch模型文件(.pt后缀)所在路径,而且需要是 torchscript格式的模型。 必填参数。
input_size_list :每个输入节点对应的图片的尺寸和通道数。例如 [[1,224,224],[ 3,224,224]]表示有两个输入,其中一个输入的 shape 是[1,224,224],另外一个输入的 shape是[3,224,224]。必填参数。
返回值0:导入成功
-1:导入失败
构建 RKNN 模型
APIbuild
描述依照加载的模型结构及权重数据,构建对应的 RKNN模型。
参数do_quantization:是否对模型进行量化,值为 True或 False。
dataset:量化校正数据的数据集。目前支持文本文件格式,用户可以把用于校正的图片(jpg或 png格式)或 npy文件路径放到一个.txt 文件中。文本文件里每一行一条路径信息。如:
a.jpg
b.jpg

a.npy
b.npy
如有多个输入,则每个输入对应的文件用空格隔开,如:
a.jpg a2.jpg
b.jpg b2.jpg

a.npy a2.npy
b.npy b2.npy
pre_compile:模型预编译开关。预编译 RKNN 模型可以减少模型初始化时间,但是无法通过模拟器进行推理或性能评估。如果 NPU 驱动有更新,预编译模型通常也需要重新构建。
注:
1. 该选项只在 Linux x86_64 平台上有效。
2. RKNN-Toolkit-V1.0.0 及以上版本生成的预编译模型不能在 NPU 驱动版本小于  0.9.6 的设备上运行;RKNN-Toolkit-V1.0.0 以前版本生成的预编译模型不能在NPU 驱 动 版 本 大 于 等 于 0.9.6 的 设 备 上 运 行 。 驱 动 版 本 号 可 以 通 过get_sdk_version 接口查询。
rknn_batch_size:模型的输入 Batch 参数调整,默认值为 1。如果大于 1,则可以在一次推理中同时推理多帧输入图像或输入数据,如 MobileNet 模型的原始input 维度为[1, 224, 224, 3],output 维度为[1, 1001],当 rknn_batch_size 设为 4 时,input 的维度变为[4, 224, 224, 3],output 维度变为[4, 1001]。
注:
1. rknn_batch_size 的调整并不会提高一般模型在 NPU 上的执行性能,但却会显著增加内存消耗以及增加单帧的延迟。
2. rknn_batch_size 的调整可以降低超小模型在 CPU 上的消耗,提高超小模型的平均帧率。(适用于模型太小,CPU 的开销大于 NPU 的开销)。
3. rknn_batch_size 的值建议小于 32,避免内存占用太大而导致推理失败。
4. rknn_batch_size 修改后,模型的 input/output 维度会被修改,使用 inference 推理模型时需要设置相应的 input 的大小,后处理时,也需要对返回的 outputs 进行处理。
返回值0:构建成功

-1:构建失败

导出 RKNN 模型

通过该接口导出 RKNN 模型文件,用于模型部署。

APIexport_rknn
描述将 RKNN模型保存到指定文件中(.rknn 后缀)。
参数export_path:导出模型文件的路径。
返回值0:导入成功 ;
-1:导入失败
 加载 RKNN模型
APIload_rknn
描述加载 RKNN 模型。
参数path:RKNN模型文件路径。
load_model_in_npu:是否直接加载npu中的rknn模型。其中path为rknn 模型在npu中的路径。只有当RKNN-Toolkit运行在RK3399Pro Linux 开发板或连有 NPU 设备 的 PC 上时才可以设为 True。默认值为 False。
返回值0:导入成功 ;
-1:导入失败
初始化运行时环境

在模型推理或性能评估之前,必须先初始化运行时环境,明确模型在的运行平台(具体的目标硬件平台或软件模拟器)

APIinit_runtime
描述初始化运行时环境。确定模型运行的设备信息(硬件平台信息、设备 ID);性能评估时是否启用debug 模式,以获取更详细的性能信息。
参数target:目标硬件平台,目前支持“rk3399pro”、“rk1806”、“rk1808”、“rv1109”、 “rv1126”。默认为 None,即在 PC 使用工具时,模型在模拟器上运行,在RK3399Pro Linux 开发板运行时,模型在RK3399Pro自带NPU上运行,否则在设定的target上 运行。其中“rk1808”包含了TB-RK1808 AI 计算棒。
device_id:设备编号,如果PC连接多台设备时,需要指定该参数,设备编号可以通过”list_devices”接口查看。默认值为 None。
     注:MAC OS X 系统当前版本还不支持多个设备。
perf_debug:进行性能评估时是否开启debug 模式。在 debug 模式下,可以获取到每一层的运行时间,否则只能获取模型运行的总时间。默认值为 False。
eval_mem: 是否进入内存评估模式。进入内存评估模式后,可以调用 eval_memory 接口获取模型运行时的内存使用情况。默认值为 False。
async_mode:是否使用异步模式。调用推理接口时,涉及设置输入图片、模型推理、获取推理结果三个阶段。如果开启了异步模式,设置当前帧的输入将与推理上一帧同时进行,所以除第一帧外,之后的每一帧都可以隐藏设置输入的时间,从而提升性能。 在异步模式下,每次返回的推理结果都是上一帧的。该参数的默认值为 False。
返回值0:构建成功
-1:构建失败
模型推理

在进行模型推理前,必须先构建或加载一个 RKNN 模型。

APIinference
描述对当前模型进行推理,返回推理结果。
如果 RKNN-Toolkit运行在PC上,且初始化运行环境时设置 target 为Rockchip NPU设备,得到的是模型在硬件平台上的推理结果。
如果 RKNN-Toolkit 运行在PC上,且初始化运行环境时没有设置 target,得到的是模型在模拟器上的推理结果。模拟器可以模拟 RK1808,也可以模拟RV1126,具体模拟哪款芯片,取决于RKNN 模型的 target_platform 参数值.
如果 RKNN-Toolkit运行在 RK3399Pro Linux开发板上,得到的是模型在实际硬件上的推理结果。
参数inputs:待推理的输入,如经过 cv2 处理的图片。格式是 ndarray list。
data_type:输入数据的类型,可填以下值:’float32’, ‘float16’, ‘int8’, ‘uint8’, ‘int16’。默认值为’uint8’。
data_format:数据模式,可以填以下值: “nchw”, “nhwc”。默认值为’nhwc’。这两个的 不同之处在于 channel 放置的位置。
inputs_pass_through:将输入透传给NPU 驱动。非透传模式下,在将输入传给NPU驱动之前,工具会对输入进行减均值、除方差等操作;而透传模式下,不会做这些操作。这个参数的值是一个数组,比如要透传input0,不透彻input1,则这个参数的值为[1, 0]。默认值为None,即对所有输入都不透传。
返回值results:推理结果,类型是 ndarray list。

 模型性能评估

APIeval_perf
描述评估模型性能。模型运行在PC上,初始化运行环境时不指定 target,得到的是模型在模拟器上运行的性能数据,包含逐层的运行时间及模型完整运行一次需要的时间。模拟器可以模拟 RK1808,也可以模拟 RV1126,具体模拟哪款芯片,取决于RKNN模型的target_platform参数值。 模型运行在与PC连接的Rockchip NPU上,且初始化运行环境时设置perf_debug为False,则获得的是模型在硬件上运行的总时间;如果设置perf_debug为 True,除了返回总时间外,还将返回每一层的耗时情况。模型运行在RK3399Pro Linux开发板上时,如果初始化运行环境时设置perf_debug为False,获得的也是模型在硬件上运行的总时间;如果设置perf_debug为 True,返回总时间及每一层的耗时情况
参数loop_cnt: 指定RKNN模型推理次数,用于计算平均推理时间。该参数只在init_runtime中的 target为非模拟器,且perf_debug设成 False时生效。该参数数据类型为整型,默认值为 1。
返回值perf_result:性能评估结果,详细说明请参考 5.3 章节。
量化精度分析
APIaccuracy_analysis
描述逐层对比浮点模型和量化模型的输出结果,输出余弦距离和欧式距离,用于分析量化模型精度下降原因。
注:
1.该接口在build或hybrid_quantization_step1或 hybrid_quantization_step2之后调用,并且原始模型应该为浮点模型,否则会调用失败。
2. 该接口使用的量化方式与 config 中指定的一致。
参数inputs:包含输入图像或数据的数据集文本文件(与量化校正数据集 dataset 格式相同, 但只能包含一组输入)。
output_dir:输出目录,所有快照都保存在该目录。该目录内容的详细说明见 4.3.3 章 节。
calc_qnt_error:是否计算量化误差(默认为 True)。
target: 指定设备类型。如果指定 target,在逐层量化误差分析时,将连接到 NPU上获取每一层的真实结果,跟浮点模型结果相比较。这样可以更准确的反映实际运行时的误差。
device_id: 如果 PC 连接了多个NPU设备,需要指定具体的设备编号。
dump_file_type: 精度分析过程中会输出模型每一层的结果,这个参数指定了输出文件的类型。有效值为’tensor’和’npy’,默认值是’tensor’。如果指定数据类型为’npy’, 可以减少精度分析的耗时。
返回值0:成功
-1:失败
 导出预编译模型(在线预编译)

构建RKNN模型时,可以指定预编译选项以导出预编译模型,这被称为离线编译。同样,RKNN Toolkit 也提供在线编译的接口:export_rknn_precompile_model。使用该接口,可以将普通 RKNN 模型转成预编译模型。

APIexport_rknn_precompile_model
描述经过在线编译后导出预编译模型。
注:
1. 使用该接口前必须先调用 load_rknn 接口加载普通 rknn 模型;
2. 使用该接口前必须调用 init_runtime 接口初始化模型运行环境,target 必须是RK NPU 设备,不能是模拟器;而且要设置 rknn2precompile 参数为 True。
参数export_path: 导出模型路径。必填参数。
返回值0:成功
-1:失败

 模型部署示例

在EASY-EAI编译环境下,在例程目录执行以下指令把可执行程序推送到开发板端:

cp yolov5_detect_demo_release/ /mnt/userdata/ -rf

通过按键Ctrl+Shift+T创建一个新窗口,执行adb shell命令,进入板卡运行环境:

adb shell

进入板卡后,定位到例程上传的位置,如下所示:

 cd /userdata/yolov5_detect_demo_release/

运行例程命令如下所示:

./yolov5_detect_demo

 执行结果如下图所示:

退出板卡环境,取回测试图片:

exit
adb pull /userdata/yolov5_detect_demo_release/result.jpg .

模型部署API

量化和反量化

零拷贝

针对 RGB 或 BGR 输入数据,实现 输入零拷贝的步骤如下:

       1)三个通道的均值是相同的整数同时归一化的缩放因子相同。

       2)在 rknn-toolkit 的 config 函数中,设置 force_builtin_perm=True,导出 NHWC输入的 RKNN 模型。

       3)使用 rknn_inputs_map 接口,获取输入 tensor 内存地址信息。

       4)往内存地址填充输入数据,比如调用 RGA 缩放函数,目标地址使用 rknn_inputs_map获取的物理地址。

       5)调用 rknn_inputs_sync 接口。

       6)调用 rknn_run 接口。

       7)调用获取输出接口。

API详细说明
rknn_init

       rknn_init初始化函数将创建 rknn_context 对象、加载 RKNN 模型以及根据 flag执行 特定的初始化行为。

APIrknn_init
功能初始化 rknn
参数rknn_context *context:rknn_context指针。函数调用之后,context 将会被赋值。
void *model:RKNN 模型的二进制数据。
uint32_t size:模型大小。
uint32_t flag:特定的初始化标志。目前 RK1808 平台仅支持以下标志: RKNN_FLAG_COLLECT_PERF_MASK:打开性能收集调试开关,打开之后能够通过rknn_query 接口查询网络每层运行时间。需要注意,该标志被设置后rknn_run的运行时间将会变长。
返回值int错误码(见rknn 返回值错误码)。
 rknn_destroy

       rknn_destroy 函数将释放传入的 rknn_context及其相关资源。

APIrknn_destroy
功能销毁 rknn_context 对象及其相关资源。
参数rknn_context context:要销毁的 rknn_context 对象。
返回值int 错误码(见 rknn 返回值错误码)。
rknn_query

       rknn_query 函数能够查询获取到模型输入输出、运行时间以及 SDK 版本等信息。

APIrknn_query
功能查询模型与 SDK 的相关信息。
参数rknn_context context:rknn_context 对象。
rknn_query_cmd cmd:查询命令。
void* info:存放返回结果的结构体变量。
uint32_t size:info 对应的结构体变量的大小。
返回值int 错误码(见 rknn 返回值错误码
 rknn_run

       rknn_run函数将执行一次模型推理,调用之前需要先通过rknn_inputs_set函数设置输入数据。

APIrknn_run
功能执行一次模型推理。
参数rknn_context context:rknn_context 对象。
rknn_run_extend* extend:保留扩展,当前没有使用,传入 NULL 即可。
返回值

int 错误码(见 rknn 返回值错误码

AI教程

Yolov5

训练完毕后,在./runs/train/exp/weights/best.pt生成通过验证集测试的最好结果的模型。同时可以执行模型预测,初步评估模型的效果:

python detect.py --source data/images --weights ./runs/train/exp/weights/best.pt --conf 0.5

  算法部署到EAI-BOX1000需要转换为RKNN模型,而转换RKNN之前可以把模型先转换为ONNX模型,同时会生成best.anchors.txt:

python export.py --include onnx --rknpu RV1126 --weights ./runs/train/exp/weights/best.pt

后续详见上文模型转换部分

自定义算法

然后把编译好的结果部署到板卡中。

cp Release/Model/modelCfg.ini /mnt/userdata/apps/Solution/Model/
cp Release/subSys_Analyzer /mnt/userdata/apps/Solution/

开发指南

打开modelCfg.ini,文档内容如下所示。用户可根据如下说明新增一组算法配置。

若添加的算法是用户自定义的算法,则进行如下所示操作:

若添加的算法是用户自定义的算法,则对CMakeLists.txt进行如下修改:

 若添加的算法是我司自研的算法,则对CMakeLists.txt进行如下修改:

修改algorithmProcess.h

修改algorithmProcess.cpp

算法逻辑处理以及上报告警,algorithmProcess会分别被n条线程调用,因此在algorithmProcess中做任何处理,每条线程都是一样的,如果想对不同的线程进行差异处理,可以利用参数列表中的ChannelInfo_t chnInfo来加以区分。下面对该函数进行详细解析。

用户开发好自定义的算法以后,执行./build.sh,就可以得到以下的一个Release目录。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值