README.md 13.4 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

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. [**建议**]直接下载,预测库下载链接如下:
25 26 27 28 29
      |平台| 架构 | 预测库下载链接|
      |-|-|-|
      |Android| arm7 | [inference_lite_lib](https://github.com/PaddlePaddle/Paddle-Lite/releases/download/v2.10-rc/inference_lite_lib.android.armv7.clang.c++_static.with_extra.with_cv.tar.gz) |
      | Android | arm8 | [inference_lite_lib](https://github.com/PaddlePaddle/Paddle-Lite/releases/download/v2.10-rc/inference_lite_lib.android.armv8.clang.c++_static.with_extra.with_cv.tar.gz)  |
      | Android | arm8(FP16) | [inference_lite_lib](https://github.com/PaddlePaddle/Paddle-Lite/releases/download/v2.10-rc/inference_lite_lib.android.armv8_clang_c++_static_with_extra_with_cv_with_fp16.tiny_publish.zip)  |
G
Guanghua Yu 已提交
30

G
Guanghua Yu 已提交
31 32
**注意**: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 已提交
33 34 35 36 37 38 39

2. 编译Paddle-Lite得到预测库,Paddle-Lite的编译方式如下:
```shell
git clone https://github.com/PaddlePaddle/Paddle-Lite.git
cd Paddle-Lite
# 如果使用编译方式,建议使用develop分支编译预测库
git checkout develop
40 41 42 43
# FP32
./lite/tools/build_android.sh --arch=armv8 --toolchain=clang --with_cv=ON --with_extra=ON
# FP16
./lite/tools/build_android.sh --arch=armv8 --toolchain=clang --with_cv=ON --with_extra=ON --with_arm82_fp16=ON
G
Guanghua Yu 已提交
44 45 46 47
```

**注意**:编译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 已提交
48
直接下载预测库并解压后,可以得到`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 已提交
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
预测库的文件目录如下:

```
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工具
G
Guanghua Yu 已提交
85
安装`paddle_lite_opt`工具有如下两种方法:
G
Guanghua Yu 已提交
86 87
1. [**建议**]pip安装paddlelite并进行转换
    ```shell
G
Guanghua Yu 已提交
88
    pip install paddlelite==2.10rc
G
Guanghua Yu 已提交
89 90
    ```

G
Guanghua Yu 已提交
91
2. 源码编译Paddle-Lite生成`paddle_lite_opt`工具
G
Guanghua Yu 已提交
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 123 124 125 126 127

    模型优化需要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 已提交
128
下面以PaddleDetection中的 `PicoDet` 模型为例,介绍使用`paddle_lite_opt`完成预训练模型到inference模型,再到Paddle-Lite优化模型的转换。
G
Guanghua Yu 已提交
129 130 131 132 133 134

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

# 将预训练模型导出为inference模型
G
Guanghua Yu 已提交
135 136
python tools/export_model.py -c configs/picodet/picodet_s_320_coco.yml \
              -o weights=https://paddledet.bj.bcebos.com/models/picodet_s_320_coco.pdparams --output_dir=output_inference
G
Guanghua Yu 已提交
137 138

# 将inference模型转化为Paddle-Lite优化模型
139
# FP32
G
Guanghua Yu 已提交
140
paddle_lite_opt  --valid_targets=arm --model_file=output_inference/picodet_s_320_coco/model.pdmodel --param_file=output_inference/picodet_s_320_coco/model.pdiparams --optimize_out=output_inference/picodet_s_320_coco/model
141 142
# FP16
paddle_lite_opt  --valid_targets=arm --model_file=output_inference/picodet_s_320_coco/model.pdmodel --param_file=output_inference/picodet_s_320_coco/model.pdiparams --optimize_out=output_inference/picodet_s_320_coco/model --enable_fp16=true
Z
zhiboniu 已提交
143 144

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

G
Guanghua Yu 已提交
148
最终在output_inference/picodet_s_320_coco/文件夹下生成`model.nb``infer_cfg.json`的文件。
G
Guanghua Yu 已提交
149 150 151 152 153 154

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

### 2.2 与手机联调

首先需要进行一些准备工作。
155
1. 准备一台arm8的安卓手机,如果编译的预测库是armv7,则需要arm7的手机,并修改Makefile中`ARM_ABI=arm7`
G
Guanghua Yu 已提交
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
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 已提交
183
4. 编译lite部署代码生成移动端可执行文件
G
Guanghua Yu 已提交
184 185

```shell
Z
zhiboniu 已提交
186
cd {PadddleDetection_Root}
G
Guanghua Yu 已提交
187 188 189
cd deploy/lite/

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

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

Z
zhiboniu 已提交
194 195 196
cd $inference_lite_path/demo/cxx/lite

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

```

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

Z
zhiboniu 已提交
204
```shell
205
mkdir deploy
G
Guanghua Yu 已提交
206
cp main *runtime_config.json deploy/
Z
zhiboniu 已提交
207 208 209
cd deploy
mkdir model_det
mkdir model_keypoint
G
Guanghua Yu 已提交
210

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

G
Guanghua Yu 已提交
215
# 如果需要关键点模型,则只需操作:
Z
zhiboniu 已提交
216 217
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 已提交
218

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

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

Z
zhiboniu 已提交
226 227 228 229 230
执行完成后,deploy文件夹下将有如下文件格式:

```
deploy/
|-- model_det/
G
Guanghua Yu 已提交
231
|   |--model.nb                    优化后的检测模型文件
G
Guanghua Yu 已提交
232
|   |--infer_cfg.json              检测器模型配置文件
Z
zhiboniu 已提交
233
|-- model_keypoint/
G
Guanghua Yu 已提交
234
|   |--model.nb                    优化后的关键点模型文件
G
Guanghua Yu 已提交
235 236 237 238 239
|   |--infer_cfg.json              关键点模型配置文件
|-- main                           生成的移动端执行文件
|-- det_runtime_config.json        目标检测执行时参数配置文件
|-- keypoint_runtime_config.json   关键点检测执行时参数配置文件
|-- libpaddle_light_api_shared.so  Paddle-Lite库文件
Z
zhiboniu 已提交
240 241 242
```

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

```shell
Z
zhiboniu 已提交
246 247 248 249
{
  "model_dir_det": "./model_det/",              #检测器模型路径
  "batch_size_det": 1,                          #检测预测时batchsize
  "threshold_det": 0.5,                         #检测器输出阈值
G
Guanghua Yu 已提交
250 251
  "image_file": "demo.jpg",                     #测试图片
  "image_dir": "",                              #测试图片文件夹
G
Guanghua Yu 已提交
252
  "run_benchmark": true,                       #性能测试开关
G
Guanghua Yu 已提交
253 254 255 256 257 258 259
  "cpu_threads": 4                              #线程数
}
```

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

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

Z
zhiboniu 已提交
272 273 274
```shell
# 将上述deploy文件夹push到手机上
adb push deploy /data/local/tmp/
G
Guanghua Yu 已提交
275 276

adb shell
Z
zhiboniu 已提交
277 278
cd /data/local/tmp/deploy
export LD_LIBRARY_PATH=/data/local/tmp/deploy:$LD_LIBRARY_PATH
G
Guanghua Yu 已提交
279

Z
zhiboniu 已提交
280 281
# 修改权限为可执行
chmod 777 main
G
Guanghua Yu 已提交
282 283
# 以检测为例,执行程序
./main det_runtime_config.json
G
Guanghua Yu 已提交
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
```

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

运行效果如下:

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


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

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