Loading... ## 0x00 说明 本文档中RKNN-SDK 位于 `~/rk1808_linux_v1.00_20181227/` RKNN-Toolkit 和 RKNN demo 包位于 `~/rk1808_linux_v1.00_20181227/external/rknpu/` 其中 rknn 文件夹为 RKNN demo,用于生成可在开发板上运行的可执行文件,rknn-toolkit 用于将其他模型转换成 rknn 模型并在 PC 上进行性能测试。 ## 0x01 环境配置 OS: Ubuntu 16.04 x64 以上 Python: 3.5/3.6 Tensorflow: >= 1.11.0 使用 Anaconda3 安装: [Anaconda3-2019.03-Linux-x86_64.sh](https://repo.anaconda.com/archive/Anaconda3-2019.03-Linux-x86_64.sh) 安装 ADB ```bash apt install android-tools-adb ``` 安装后配置: 由于 conda 镜像中处理 Tensorflow 1.11.0 依赖时会降低其他库的版本,这里使用 Tensorflow 1.13.1。 ```bash conda install python=3.7 conda install tensorflow=1.13.1 conda install opencv=3.4.1 pip install ~/rk1808_linux_v1.00_20181227/external/rknpu/rknn-toolkit/packages/rknn_toolkit-0.9.8-cp36-cp36m-linux_x86_64.whl ``` ## 0x02 转换模型 转换模型使用 RKNN-Toolkit,SDK 中提供了三种基于 MobileNet 的转换工具,位于 `~/rk1808_linux_v1.00_20181227/external/rknpu/rknn-toolkit/example` 目录下,本文档以使用 mobilenet-ssd 转换 Tensorflow 的 `.pb` 模型为例。 进入 `mobilenet-ssd` 目录下,运行 `ssd.py` ```bash cd ~/rk1808_linux_v1.00_20181227/external/rknpu/rknn-toolkit/example/mobilenet-ssd python ssd.py ``` 转换成功后输出如下: ```bash --> Loading model done --> Building model done --> Init runtime environment done --> Running model done inference resule: [array([[ 0.89453125, 0.18859863, -3.0390625 , ..., -0.0308075 , -2.4863281 , -0.10644531]], dtype=float32), array([[ 2.4785156, -4.7382812, -7.9335938, ..., -10.0859375, -9.625 , -10.4140625]], dtype=float32)] ======================================================================== Performance ======================================================================== Layer Id Name Time(us) 0 convolution.relu.pooling.layer2_3 1005 1 activation.layer_3 510 2 convolution.relu.pooling.layer2_2 774 3 activation.layer_3 510 '''''' 91 fullyconnected.relu.layer_3 17 92 tensor.ranspose_3 4 93 tensor.ranspose_3 5 Total Time(us): 165830 FPS(800MHz): 6.03 ======================================================================== ``` 转换其他模型: 修改 `ssd.py` 中 `rknn.load_tensorflow`,`tf_pb` 为 `.pb` 模型文件的路径;`input` 为模型输入节点;`output` 为模型输出节点;`input_size_list` 为输入节点对应的图片尺寸和通道数。 `rknn.config` 方法中 `channel_mean_value` 为模型均值;`reorder_channel` 为通道顺序,`0 1 2` 为 RGB,`2 1 0` 为 BGR。 `rknn.build` 方法中 `do_quantization` 为生成 rknn 模型是否进行量化的控制参数,`dataset` 为进行量化时使用的图片,建议大于 200 张。 如果将 `do_quantization` 设置为 `True`,根据情况(可能报错)需要在 `rknn.config` 方法中添加参数 `batch_size` 和 `epochs`,如果性能足够可以设置 `batch_size=200,epochs=1`,如果显存不足可以设置为 `batch_size=1,epochs=200`。 `rknn.export_rknn` 方法用于设置 rknn 模型输出路径及文件名称。 `rknn.export_rknn` 方法后面的代码可以对导出的 rknn 模型进行性能评估。 **注意:如果在性能评估或检测时发生检测出目标数量过多的情况,请检查 `rknn_inference` 方法输出的数组元素顺序是否需要调换,例如:** ```python outputs = rknn.inference(inputs=[img]) predoctions = outputs[1].reshape((1, NUM_RESULTS, 4)) outputClasses = outputs[0].reshape((1, NUM_RESULTS, NUM_CLASSES)) ``` 其中 `predictions` 在 SDK 提供的模型中使用 `outputs[0]` 中的值,而在自行转换的模型中需要使用 `outputs[1]`,的值,`outputClasses` 同理。 如果在转换模型时发现了这个问题,在 demo 的 `main.cc` 中也需要修改 `outputs` 数组顺序,例如: ```c postProcessSSD((float *)(outputs[1].buf), (float *)(outputs[0].buf). orig_img.cols, orig_img.rows, &detect_result_group); ``` 如果出现了上述错误,应尝试将这段代码修改为: ```c postProcessSSD((float *)(outputs[0].buf), (float *)(outputs[1].buf). orig_img.cols, orig_img.rows, &detect_result_group); ``` ## 0x03 在开发板上运行 demo SDK 中提供了三种基于 MobileNet 的 demo 位于 `~/rk1808_linux_v1.00_20181227/external/rknpu/rknn/examples` 目录下,本文档以调用由 MobileNet-SSD Tensorflow pb 模型转换的 rknn 模型使用 rknn_ssd_demo 对 `road.bmp` 进行目标检测为例。  过程如下: ### 进入 demo 目录,建立 `build` 文件夹 ```bash cd ~/rk1808_linux_v1.00_20181227/external/rknpu/rknn/examples/rknn_ssd_demo mkdir build cd build ``` ### 编译 ```bash cmake .. make make install cd .. ``` ### 此时 demo 目录下应出现 `install` 文件夹,如果没有请检查环境是否符合要求 ### 将生成的 rknn 模型放入 `install/rknn_ssd_demo` 文件夹 例如生成的 rknn 模型位于 `~/rk1808_linux_v1.00_20181227/external/rknpu/rknn-toolkit/examples/mobilenet-ssd` 模型名称为 `ssd_mobilenet_v1_coco.rknn` ```bash cp ../../../rknn-toolkit/example/mobilenet-ssd/ssd_mobilenet_v1_coco.rknn ./install/rknn_ssd_demo ``` ### 测试 adb 连接 ```bash adb devices ``` 如果返回类似如下的数据,则连接成功,否则请检查设备与开发机的连接 ```bash List of devices attached 0123456789ABCDEF device ``` ### 在设备中建立 `/userdata/rknn_ssd_demo` 目录并将 `install` 下的 `rknn_ssd_demo` 文件夹 push 进创建的目录中 ```bash adb shell mkdir /userdata/rknn_ssd_demo adb push ./install/rknn_ssd_demo/* /userdata/rknn_ssd_demo ``` ### 进入设备终端并进行检测 ```bash adb shell cd /userdata/rknn_ssd_demo ./rknn_ssd_demo ssd_mobilenet_v1_coco.rknn road.bmp ``` 检测成功后输出如下: ```bash Loading model ... model input num: 1, output num: 2 input tensors: index=0 name = n_dims=4 dims=[1 3 300 300] n_elems=270000 size=540000 fmt=0 type=1 qnt_type=0 fl=-84 zp=-1311164756 scale=0.000000 output tensors: index=0 name = n_dims=4 dims=[1 1917 1 4] n_elems=7668 size=15336 fmt=0 type=1 qnt_type=0 fl=-84 zp=-1311164756 scale=0.000000 index=1 name = n_dims=3 dims=[0 1 1917 91] n_elems=174447 size=348894 fmt=0 type=1 qnt_type=0 fl=-84 zp=-1311164756 scale=0.000000 rknn_run loadLabelName ssd - loadLabelNameloadBoxPriors ValidCount: 25 person @ (15 127 55 209) 0.984575 bicycle @ (170 158 283 233) @ 0.958382 person @ (107 119 152 192) 0.948155 car @ (148 134 215 173) 0.930078 person @ (207 112 256 218) 0.838812 person @ (50 135 58 158) 0.470782 person @ (83 133 92 156) 0.433082 ``` ### 退出设备终端并将检测后生成的 out.jpg 拉回本地 ```bash exit adb pull /userdata/rknn_ssd_demo/out.jpg ./ ```  ## 0x04 自动化脚本 该部分中所有操作均在 demo 目录下进行 ### 在设备中检测 建立 `adb_run_rknn_ssd` 文件,并写入如下命令,用于在开发机中直接导入设备终端的命令。 ```bash cd /userdata/rknn_ssd_demo ./rknn_ssd_demo ssd_mobilenet_v1_coco.rknn road.bmp exit ``` ### 在设备中执行检测并将 `out.jpg` 拉到本地 ```bash $ adb shell < adb_run_rknn_ssd && \ > adb pull /userdata/rknn_ssd_demo/out.jpg ./ ``` ### 重新编译代码,在设备中执行检测,并将 `out.jpg` 拉到本地 ```bash cd build/ && \ rm -rf * && \ cmake .. && \ make && \ make install && \ cd .. && \ adb shell mkdir rknn_ssd_demo && \ adb push ./install/rknn_ssd_demo/* /userdata/rknn_ssd_demo/ && \ adb shell < adb_run_rknn_ssd && \ adb pull /userdata/rknn_ssd_demo/out.jpg ./ ``` 最后修改:2022 年 01 月 03 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏