README.md 12.7 KB
Newer Older
G
Guanghua Yu 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
# Paddle-Lite端侧部署

本教程将介绍基于[Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite) 在移动端部署PaddleDetection模型的详细步骤。

Paddle Lite是飞桨轻量化推理引擎,为手机、IOT端提供高效推理能力,并广泛整合跨平台硬件,为端侧部署及应用落地问题提供轻量化的部署方案。

## 1. 准备环境

### 运行准备
- 电脑(编译Paddle Lite)
- 安卓手机(armv7或armv8)

### 1.1 准备交叉编译环境
交叉编译环境用于编译 Paddle Lite 和 PaddleDetection 的C++ demo。
G
Guanghua Yu 已提交
15
支持多种开发环境,不同开发环境的编译流程请参考对应文档,请确保安装完成Java jdk、Android NDK(R17以上)。
G
Guanghua Yu 已提交
16 17 18 19 20 21 22 23 24 25 26

1. [Docker](https://paddle-lite.readthedocs.io/zh/latest/source_compile/compile_env.html#docker)
2. [Linux](https://paddle-lite.readthedocs.io/zh/latest/source_compile/compile_env.html#linux)
3. [MAC OS](https://paddle-lite.readthedocs.io/zh/latest/source_compile/compile_env.html#mac-os)

### 1.2 准备预测库

预测库有两种获取方式:
1. [**建议**]直接下载,预测库下载链接如下:
      |平台|预测库下载链接|
      |-|-|
G
Guanghua Yu 已提交
27
      |Android|[arm7](https://github.com/PaddlePaddle/Paddle-Lite/releases/download/v2.9.1/inference_lite_lib.android.armv7.clang.c++_static.with_extra.with_cv.tar.gz) / [arm8](https://github.com/PaddlePaddle/Paddle-Lite/releases/download/v2.9.1/inference_lite_lib.android.armv8.clang.c++_static.with_extra.with_cv.tar.gz)|
G
Guanghua Yu 已提交
28

G
Guanghua Yu 已提交
29 30
**注意**:1. 如果是从 Paddle-Lite [官方文档](https://paddle-lite.readthedocs.io/zh/latest/quick_start/release_lib.html#android-toolchain-gcc)下载的预测库,注意选择`with_extra=ON,with_cv=ON`的下载链接。2. 目前只提供Android端demo,IOS端demo可以参考[Paddle-Lite IOS demo](https://github.com/PaddlePaddle/Paddle-Lite-Demo/tree/master/PaddleLite-ios-demo)

G
Guanghua Yu 已提交
31 32 33 34 35 36 37 38 39 40 41 42

2. 编译Paddle-Lite得到预测库,Paddle-Lite的编译方式如下:
```shell
git clone https://github.com/PaddlePaddle/Paddle-Lite.git
cd Paddle-Lite
# 如果使用编译方式,建议使用develop分支编译预测库
git checkout develop
./lite/tools/build_android.sh  --arch=armv8  --with_cv=ON --with_extra=ON
```

**注意**:编译Paddle-Lite获得预测库时,需要打开`--with_cv=ON --with_extra=ON`两个选项,`--arch`表示`arm`版本,这里指定为armv8,更多编译命令介绍请参考[链接](https://paddle-lite.readthedocs.io/zh/latest/source_compile/compile_andriod.html#id2)

G
Guanghua Yu 已提交
43
直接下载预测库并解压后,可以得到`inference_lite_lib.android.armv8.clang.c++_static.with_extra.with_cv/`文件夹,通过编译Paddle-Lite得到的预测库位于`Paddle-Lite/build.lite.android.armv8.gcc/inference_lite_lib.android.armv8/`文件夹下。
G
Guanghua Yu 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
预测库的文件目录如下:

```
inference_lite_lib.android.armv8/
|-- cxx                                        C++ 预测库和头文件
|   |-- include                                C++ 头文件
|   |   |-- paddle_api.h
|   |   |-- paddle_image_preprocess.h
|   |   |-- paddle_lite_factory_helper.h
|   |   |-- paddle_place.h
|   |   |-- paddle_use_kernels.h
|   |   |-- paddle_use_ops.h
|   |   `-- paddle_use_passes.h
|   `-- lib                                           C++预测库
|       |-- libpaddle_api_light_bundled.a             C++静态库
|       `-- libpaddle_light_api_shared.so             C++动态库
|-- java                                     Java预测库
|   |-- jar
|   |   `-- PaddlePredictor.jar
|   |-- so
|   |   `-- libpaddle_lite_jni.so
|   `-- src
|-- demo                                     C++和Java示例代码
|   |-- cxx                                  C++  预测库demo
|   `-- java                                 Java 预测库demo
```

## 2 开始运行

### 2.1 模型优化

Paddle-Lite 提供了多种策略来自动优化原始的模型,其中包括量化、子图融合、混合调度、Kernel优选等方法,使用Paddle-Lite的`opt`工具可以自动对inference模型进行优化,目前支持两种优化方式,优化后的模型更轻量,模型运行速度更快。

**注意**:如果已经准备好了 `.nb` 结尾的模型文件,可以跳过此步骤。

#### 2.1.1 安装paddle_lite_opt工具
安装paddle_lite_opt工具有如下两种方法:
1. [**建议**]pip安装paddlelite并进行转换
    ```shell
    pip install paddlelite
    ```

2. 源码编译Paddle-Lite生成opt工具

    模型优化需要Paddle-Lite的`opt`可执行文件,可以通过编译Paddle-Lite源码获得,编译步骤如下:
    ```shell
    # 如果准备环境时已经clone了Paddle-Lite,则不用重新clone Paddle-Lite
    git clone https://github.com/PaddlePaddle/Paddle-Lite.git
    cd Paddle-Lite
    git checkout develop
    # 启动编译
    ./lite/tools/build.sh build_optimize_tool
    ```

    编译完成后,`opt`文件位于`build.opt/lite/api/`下,可通过如下方式查看`opt`的运行选项和使用方式;
    ```shell
    cd build.opt/lite/api/
    ./opt
    ```

    `opt`的使用方式与参数与上面的`paddle_lite_opt`完全一致。

之后使用`paddle_lite_opt`工具可以进行inference模型的转换。`paddle_lite_opt`的部分参数如下:

|选项|说明|
|-|-|
|--model_file|待优化的PaddlePaddle模型(combined形式)的网络结构文件路径|
|--param_file|待优化的PaddlePaddle模型(combined形式)的权重文件路径|
|--optimize_out_type|输出模型类型,目前支持两种类型:protobuf和naive_buffer,其中naive_buffer是一种更轻量级的序列化/反序列化实现,默认为naive_buffer|
|--optimize_out|优化模型的输出路径|
|--valid_targets|指定模型可执行的backend,默认为arm。目前可支持x86、arm、opencl、npu、xpu,可以同时指定多个backend(以空格分隔),Model Optimize Tool将会自动选择最佳方式。如果需要支持华为NPU(Kirin 810/990 Soc搭载的达芬奇架构NPU),应当设置为npu, arm|

更详细的`paddle_lite_opt`工具使用说明请参考[使用opt转化模型文档](https://paddle-lite.readthedocs.io/zh/latest/user_guides/opt/opt_bin.html)

`--model_file`表示inference模型的model文件地址,`--param_file`表示inference模型的param文件地址;`optimize_out`用于指定输出文件的名称(不需要添加`.nb`的后缀)。直接在命令行中运行`paddle_lite_opt`,也可以查看所有参数及其说明。


#### 2.1.3 转换示例

G
Guanghua Yu 已提交
123
下面以PaddleDetection中的 `ppyolo` 模型为例,介绍使用`paddle_lite_opt`完成预训练模型到inference模型,再到Paddle-Lite优化模型的转换。
G
Guanghua Yu 已提交
124 125 126 127 128 129 130 131 132

```shell
# 进入PaddleDetection根目录
cd PaddleDetection_root_path

# 将预训练模型导出为inference模型
python tools/export_model.py -c configs/ppyolo/ppyolo_tiny_650e_coco.yml -o weights=https://paddledet.bj.bcebos.com/models/ppyolo_tiny_650e_coco.pdparams

# 将inference模型转化为Paddle-Lite优化模型
G
Guanghua Yu 已提交
133
paddle_lite_opt  --valid_targets=arm --model_file=output_inference/ppyolo_tiny_650e_coco/model.pdmodel --param_file=output_inference/ppyolo_tiny_650e_coco/model.pdiparams --optimize_out=output_inference/ppyolo_tiny_650e_coco/model
Z
zhiboniu 已提交
134 135 136

# 将inference模型配置转化为json格式
python deploy/lite/convert_yml_to_json.py output_inference/ppyolo_tiny_650e_coco/infer_cfg.yml
G
Guanghua Yu 已提交
137 138
```

Z
zhiboniu 已提交
139
最终在output_inference/ppyolo_tiny_650e_coco/文件夹下生成`ppyolo_tiny.nb``infer_cfg.json`的文件。
G
Guanghua Yu 已提交
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

**注意**`--optimize_out` 参数为优化后模型的保存路径,无需加后缀`.nb``--model_file` 参数为模型结构信息文件的路径,`--param_file` 参数为模型权重信息文件的路径,请注意文件名。

### 2.2 与手机联调

首先需要进行一些准备工作。
1. 准备一台arm8的安卓手机,如果编译的预测库和opt文件是armv7,则需要arm7的手机,并修改Makefile中`ARM_ABI = arm7`
2. 电脑上安装ADB工具,用于调试。 ADB安装方式如下:

    2.1. MAC电脑安装ADB:

    ```shell
    brew cask install android-platform-tools
    ```
    2.2. Linux安装ADB
    ```shell
    sudo apt update
    sudo apt install -y wget adb
    ```
    2.3. Window安装ADB

    win上安装需要去谷歌的安卓平台下载ADB软件包进行安装:[链接](https://developer.android.com/studio)

3. 手机连接电脑后,开启手机`USB调试`选项,选择`文件传输`模式,在电脑终端中输入:

```shell
adb devices
```
如果有device输出,则表示安装成功,如下所示:
```
List of devices attached
744be294    device
```

Z
zhiboniu 已提交
174
4. 编译lite部署代码生成移动端可执行文件
G
Guanghua Yu 已提交
175 176

```shell
Z
zhiboniu 已提交
177
cd {PadddleDetection_Root}
G
Guanghua Yu 已提交
178 179 180
cd deploy/lite/

inference_lite_path=/{lite prediction library path}/inference_lite_lib.android.armv8.gcc.c++_static.with_extra.with_cv/
Z
zhiboniu 已提交
181
mkdir $inference_lite_path/demo/cxx/lite
G
Guanghua Yu 已提交
182

G
Guanghua Yu 已提交
183
cp -r Makefile src/ include/ *runtime_config.json $inference_lite_path/demo/cxx/lite
G
Guanghua Yu 已提交
184

Z
zhiboniu 已提交
185 186 187 188 189
cd $inference_lite_path/demo/cxx/lite

# 执行编译,等待完成后得到可执行文件main
make ARM_ABI = arm8
#如果是arm7,则执行 make ARM_ABI = arm7 (或者在Makefile中修改该项)
G
Guanghua Yu 已提交
190 191 192

```

Z
zhiboniu 已提交
193
5. 准备优化后的模型、预测库文件、测试图像。
G
Guanghua Yu 已提交
194

Z
zhiboniu 已提交
195 196
```shell
mdkir deploy
G
Guanghua Yu 已提交
197
cp main *runtime_config.json deploy/
Z
zhiboniu 已提交
198 199 200
cd deploy
mkdir model_det
mkdir model_keypoint
G
Guanghua Yu 已提交
201

Z
zhiboniu 已提交
202 203 204
# 将优化后的模型、预测库文件、测试图像放置在预测库中的demo/cxx/detection文件夹下
cp {PadddleDetection_Root}/output_inference/ppyolo_tiny_650e_coco/model.nb ./model_det/
cp {PadddleDetection_Root}/output_inference/ppyolo_tiny_650e_coco/infer_cfg.json ./model_det/
G
Guanghua Yu 已提交
205

Z
zhiboniu 已提交
206 207 208
# 如果需要关键点模型,则只需一下操作
cp {PadddleDetection_Root}/output_inference/hrnet_w32_256x192/model.nb ./model_keypoint/
cp {PadddleDetection_Root}/output_inference/hrnet_w32_256x192/infer_cfg.json ./model_keypoint/
G
Guanghua Yu 已提交
209

Z
zhiboniu 已提交
210 211
# 将测试图像复制到deploy文件夹中
cp [your_test_img].jpg ./demo.jpg
G
Guanghua Yu 已提交
212

Z
zhiboniu 已提交
213 214
# 将C++预测动态库so文件复制到deploy文件夹中
cp ../../../cxx/lib/libpaddle_light_api_shared.so ./
G
Guanghua Yu 已提交
215 216
```

Z
zhiboniu 已提交
217 218 219 220 221
执行完成后,deploy文件夹下将有如下文件格式:

```
deploy/
|-- model_det/
G
Guanghua Yu 已提交
222 223
|   |--mdoel.nb                    优化后的检测模型文件
|   |--infer_cfg.json              检测器模型配置文件
Z
zhiboniu 已提交
224
|-- model_keypoint/
G
Guanghua Yu 已提交
225 226 227 228 229 230
|   |--mdoel.nb                    优化后的关键点模型文件
|   |--infer_cfg.json              关键点模型配置文件
|-- main                           生成的移动端执行文件
|-- det_runtime_config.json        目标检测执行时参数配置文件
|-- keypoint_runtime_config.json   关键点检测执行时参数配置文件
|-- libpaddle_light_api_shared.so  Paddle-Lite库文件
Z
zhiboniu 已提交
231 232 233
```

**注意:**
G
Guanghua Yu 已提交
234
*  `det_runtime_config.json` 包含了目标检测的超参数,请按需进行修改:
G
Guanghua Yu 已提交
235 236

```shell
Z
zhiboniu 已提交
237 238 239 240
{
  "model_dir_det": "./model_det/",              #检测器模型路径
  "batch_size_det": 1,                          #检测预测时batchsize
  "threshold_det": 0.5,                         #检测器输出阈值
G
Guanghua Yu 已提交
241 242 243 244 245 246 247 248 249 250
  "image_file": "demo.jpg",                     #测试图片
  "image_dir": "",                              #测试图片文件夹
  "run_benchmark": false,                       #性能测试开关
  "cpu_threads": 4                              #线程数
}
```

*  `keypoint_runtime_config.json` 包含了关键点检测的超参数,请按需进行修改:
```shell
{
Z
zhiboniu 已提交
251 252 253 254 255 256
  "model_dir_keypoint": "./model_keypoint/",    #关键点模型路径(不使用需为空字符)
  "batch_size_keypoint": 8,                     #关键点预测时batchsize
  "threshold_keypoint": 0.5,                    #关键点输出阈值
  "image_file": "demo.jpg",                     #测试图片
  "image_dir": "",                              #测试图片文件夹
  "run_benchmark": false,                       #性能测试开关
G
Guanghua Yu 已提交
257
  "cpu_threads": 4                              #线程数
Z
zhiboniu 已提交
258 259
}
```
G
Guanghua Yu 已提交
260

Z
zhiboniu 已提交
261
6. 启动调试,上述步骤完成后就可以使用ADB将文件夹 `deploy/` push到手机上运行,步骤如下:
G
Guanghua Yu 已提交
262

Z
zhiboniu 已提交
263 264 265
```shell
# 将上述deploy文件夹push到手机上
adb push deploy /data/local/tmp/
G
Guanghua Yu 已提交
266 267

adb shell
Z
zhiboniu 已提交
268 269
cd /data/local/tmp/deploy
export LD_LIBRARY_PATH=/data/local/tmp/deploy:$LD_LIBRARY_PATH
G
Guanghua Yu 已提交
270

Z
zhiboniu 已提交
271 272
# 修改权限为可执行
chmod 777 main
G
Guanghua Yu 已提交
273 274
# 以检测为例,执行程序
./main det_runtime_config.json
G
Guanghua Yu 已提交
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
```

如果对代码做了修改,则需要重新编译并push到手机上。

运行效果如下:

<div align="center">
    <img src="../../docs/images/lite_demo.jpg" width="600">
</div>


## FAQ
Q1:如果想更换模型怎么办,需要重新按照流程走一遍吗?  
A1:如果已经走通了上述步骤,更换模型只需要替换 `.nb` 模型文件即可,同时要注意修改下配置文件中的 `.nb` 文件路径以及类别映射文件(如有必要)。

Q2:换一个图测试怎么做?  
Z
zhiboniu 已提交
291
A2:替换 deploy 下的测试图像为你想要测试的图像,使用 ADB 再次 push 到手机上即可。