提交 855b1547 编写于 作者: F FlyingQianMM

Merge branch 'develop' of https://github.com/PaddlePaddle/PaddleX into develop_qh

<p align="center">
<img src="./docs/images/paddlex.png" width="360" height ="60" alt="PaddleX" align="middle" />
<img src="./docs/gui/images/paddlex.png" width="360" height ="55" alt="PaddleX" align="middle" />
</p>
[![License](https://img.shields.io/badge/license-Apache%202-red.svg)](LICENSE)
......@@ -8,23 +8,38 @@
![support os](https://img.shields.io/badge/os-linux%2C%20win%2C%20mac-yellow.svg)
![QQGroup](https://img.shields.io/badge/QQ_Group-1045148026-52B6EF?style=social&logo=tencent-qq&logoColor=000&logoWidth=20)
PaddleX是基于飞桨核心框架、开发套件和工具组件的深度学习全流程开发工具。具备**全流程打通****融合产业实践****易用易集成**三大特点
**PaddleX--飞桨全功能开发套件**,集成了飞桨视觉套件(PaddleClas、PaddleDetection、PaddleSeg)、模型压缩工具PaddleSlim、可视化分析工具VisualDL、轻量化推理引擎Paddle Lite 等核心模块的能力,同时融合飞桨团队丰富的实际经验及技术积累,将深度学习开发全流程,从数据准备、模型训练与优化到多端部署实现了端到端打通,为开发者提供飞桨全流程开发的最佳实践
## 特点
**PaddleX 提供了最简化的API设计,并官方实现GUI供大家下载使用**,最大程度降低开发者使用门槛。开发者既可以应用**PaddleX GUI**快速体验深度学习模型开发的全流程,也可以直接使用 **PaddleX API** 更灵活地进行开发。
- **全流程打通**
- **数据准备**:支持[EasyData智能数据服务平台](https://ai.baidu.com/easydata/)数据协议,通过平台便捷完成智能标注,低质数据清洗工作, 同时兼容主流标注工具协议, 助力开发者更快完成数据准备工作。
- **模型训练**:集成[PaddleClas](https://github.com/PaddlePaddle/PaddleClas), [PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection), [PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg)视觉开发套件,丰富的高质量预训练模型,更快实现工业级模型效果。
- **模型调优**:内置模型可解释性模块、[VisualDL](https://github.com/PaddlePaddle/VisualDL)可视化分析组件, 提供丰富的信息更好地理解模型,优化模型。
- **多端安全部署**:内置[PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim)模型压缩工具和**模型加密部署模块**,结合Paddle Inference或[Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite)便捷完成高性能的多端安全部署。
更进一步的,如果用户需要根据自己场景及需求,定制化地对PaddleX 进行改造或集成,PaddleX 也提供很好的支持。
- **融合产业实践**
- 精选飞桨产业实践的成熟模型结构,开放案例实践教程,加速开发者产业落地。
## PaddleX 三大特点
- **易用易集成**
- 统一易用的全流程API,5步完成模型训练,10行代码实现Python/C++高性能部署。
- 提供以PaddleX为核心集成的跨平台可视化工具PaddleX-GUI,快速体验飞桨深度学习全流程。
### 全流程打通
- **数据准备**:兼容ImageNet、VOC、COCO等常用数据协议, 同时与Labelme、精灵标注助手、EasyData智能数据服务平台](https://ai.baidu.com/easydata/)等无缝衔接,全方位助力开发者更快完成数据准备工作。
- **数据预处理及增强**:提供极简的图像预处理和增强方法--Transforms,适配imgaug图像增强库,支持上百种数据增强策略,是开发者快速缓解小样本数据训练的问题。
- **模型训练**:集成[PaddleClas](https://github.com/PaddlePaddle/PaddleClas), [PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection), [PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg)视觉开发套件,提供大量精选的、经过产业实践的高质量预训练模型,使开发者更快实现工业级模型效果。
- **模型调优**:内置模型可解释性模块、[VisualDL](https://github.com/PaddlePaddle/VisualDL)可视化分析工具。使开发者可以更直观的理解模型的特征提取区域、训练过程参数变化,从而快速优化模型。
- **多端安全部署**:内置[PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim)模型压缩工具和**模型加密部署模块**,与飞桨原生预测库Paddle Inference及高性能端侧推理引擎[Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite) 无缝打通,使开发者快速实现模型的多端、高性能、安全部署。
### 融合产业实践
- **产业验证**:经过**质检****安防****巡检****遥感****零售****医疗**等十多个行业实际应用场景验证,适配行业数据格式及部署环境要求。
- **经验沉淀**:沉淀产业实践实际经验,**提供丰富的案例实践教程**,加速开发者产业落地。
- **产业开发者共建**:吸收实际产业开发者贡献代码,源于产业,回馈产业。
## 易用易集成
- **易用**:统一的全流程API,5步即可完成模型训练,10行代码实现Python/C++高性能部署。
- **易集成**:支持开发者自主改造、集成,开发出适用于自己产业需求的产品。并官方提供基于 PaddleX API 开发的跨平台可视化工具-- **PaddleX GUI**,使开发者快速体验飞桨深度学习开发全流程,并启发用户进行定制化开发。
## 安装
......@@ -53,7 +68,7 @@ pip install paddlex -i https://mirror.baidu.com/pypi/simple
### PaddleX-GUI安装
进入PaddleX官网[下载使用](https://www.paddlepaddle.org.cn/paddle/paddlex),申请下载绿色安装包,开箱即用。
Paddle-GUI的使用教程可参考[PaddleX-GUI模式使用教程](https://paddlex.readthedocs.io/zh_CN/develop/paddlex_gui/index.html)
Paddle-GUI的使用教程可参考[PaddleX-GUI模式使用教程](./docs/gui/how_to_use.md)
## 使用文档
......@@ -75,9 +90,9 @@ Paddle-GUI的使用教程可参考[PaddleX-GUI模式使用教程](https://paddle
- 项目官网: https://www.paddlepaddle.org.cn/paddle/paddlex
- PaddleX用户交流群: 1045148026 (手机QQ扫描如下二维码快速加入)
<img src="./docs/images/QQGroup.jpeg" width="195" height="300" alt="QQGroup" align="center" />
<img src="./docs/gui/images/QR.jpg" width="250" height="300" alt="QQGroup" align="center" />
## FAQ
## [FAQ](./docs/gui/faq.md)
## 更新日志
> [历史版本及更新内容](https://paddlex.readthedocs.io/zh_CN/develop/change_log.html)
......
......@@ -62,8 +62,6 @@ int main(int argc, char** argv) {
FLAGS_use_ir_optim);
// 进行预测
double total_running_time_s = 0.0;
double total_imread_time_s = 0.0;
int imgs = 1;
if (FLAGS_image_list != "") {
std::ifstream inf(FLAGS_image_list);
......@@ -79,7 +77,6 @@ int main(int argc, char** argv) {
}
imgs = image_paths.size();
for (int i = 0; i < image_paths.size(); i += FLAGS_batch_size) {
auto start = system_clock::now();
// 读图像
int im_vec_size =
std::min(static_cast<int>(image_paths.size()), i + FLAGS_batch_size);
......@@ -91,19 +88,7 @@ int main(int argc, char** argv) {
for (int j = i; j < im_vec_size; ++j) {
im_vec[j - i] = std::move(cv::imread(image_paths[j], 1));
}
auto imread_end = system_clock::now();
model.predict(im_vec, &results, thread_num);
auto imread_duration = duration_cast<microseconds>(imread_end - start);
total_imread_time_s += static_cast<double>(imread_duration.count()) *
microseconds::period::num /
microseconds::period::den;
auto end = system_clock::now();
auto duration = duration_cast<microseconds>(end - start);
total_running_time_s += static_cast<double>(duration.count()) *
microseconds::period::num /
microseconds::period::den;
for (int j = i; j < im_vec_size; ++j) {
std::cout << "Path:" << image_paths[j]
<< ", predict label: " << results[j - i].category
......@@ -112,23 +97,12 @@ int main(int argc, char** argv) {
}
}
} else {
auto start = system_clock::now();
PaddleX::ClsResult result;
cv::Mat im = cv::imread(FLAGS_image, 1);
model.predict(im, &result);
auto end = system_clock::now();
auto duration = duration_cast<microseconds>(end - start);
total_running_time_s += static_cast<double>(duration.count()) *
microseconds::period::num /
microseconds::period::den;
std::cout << "Predict label: " << result.category
<< ", label_id:" << result.category_id
<< ", score: " << result.score << std::endl;
}
std::cout << "Total running time: " << total_running_time_s
<< " s, average running time: " << total_running_time_s / imgs
<< " s/img, total read img time: " << total_imread_time_s
<< " s, average read time: " << total_imread_time_s / imgs
<< " s/img, batch_size = " << FLAGS_batch_size << std::endl;
return 0;
}
......@@ -65,11 +65,7 @@ int main(int argc, char** argv) {
FLAGS_gpu_id,
FLAGS_key,
FLAGS_use_ir_optim);
double total_running_time_s = 0.0;
double total_imread_time_s = 0.0;
int imgs = 1;
auto colormap = PaddleX::GenerateColorMap(model.labels.size());
std::string save_dir = "output";
// 进行预测
if (FLAGS_image_list != "") {
......@@ -85,7 +81,6 @@ int main(int argc, char** argv) {
}
imgs = image_paths.size();
for (int i = 0; i < image_paths.size(); i += FLAGS_batch_size) {
auto start = system_clock::now();
int im_vec_size =
std::min(static_cast<int>(image_paths.size()), i + FLAGS_batch_size);
std::vector<cv::Mat> im_vec(im_vec_size - i);
......@@ -96,17 +91,7 @@ int main(int argc, char** argv) {
for (int j = i; j < im_vec_size; ++j) {
im_vec[j - i] = std::move(cv::imread(image_paths[j], 1));
}
auto imread_end = system_clock::now();
model.predict(im_vec, &results, thread_num);
auto imread_duration = duration_cast<microseconds>(imread_end - start);
total_imread_time_s += static_cast<double>(imread_duration.count()) *
microseconds::period::num /
microseconds::period::den;
auto end = system_clock::now();
auto duration = duration_cast<microseconds>(end - start);
total_running_time_s += static_cast<double>(duration.count()) *
microseconds::period::num /
microseconds::period::den;
// 输出结果目标框
for (int j = 0; j < im_vec_size - i; ++j) {
for (int k = 0; k < results[j].boxes.size(); ++k) {
......@@ -124,7 +109,7 @@ int main(int argc, char** argv) {
// 可视化
for (int j = 0; j < im_vec_size - i; ++j) {
cv::Mat vis_img = PaddleX::Visualize(
im_vec[j], results[j], model.labels, colormap, FLAGS_threshold);
im_vec[j], results[j], model.labels, FLAGS_threshold);
std::string save_path =
PaddleX::generate_save_path(FLAGS_save_dir, image_paths[i + j]);
cv::imwrite(save_path, vis_img);
......@@ -132,15 +117,9 @@ int main(int argc, char** argv) {
}
}
} else {
auto start = system_clock::now();
PaddleX::DetResult result;
cv::Mat im = cv::imread(FLAGS_image, 1);
model.predict(im, &result);
auto end = system_clock::now();
auto duration = duration_cast<microseconds>(end - start);
total_running_time_s += static_cast<double>(duration.count()) *
microseconds::period::num /
microseconds::period::den;
// 输出结果目标框
for (int i = 0; i < result.boxes.size(); ++i) {
std::cout << "image file: " << FLAGS_image << std::endl;
......@@ -155,7 +134,7 @@ int main(int argc, char** argv) {
// 可视化
cv::Mat vis_img =
PaddleX::Visualize(im, result, model.labels, colormap, FLAGS_threshold);
PaddleX::Visualize(im, result, model.labels, FLAGS_threshold);
std::string save_path =
PaddleX::generate_save_path(FLAGS_save_dir, FLAGS_image);
cv::imwrite(save_path, vis_img);
......@@ -163,11 +142,5 @@ int main(int argc, char** argv) {
std::cout << "Visualized output saved as " << save_path << std::endl;
}
std::cout << "Total running time: " << total_running_time_s
<< " s, average running time: " << total_running_time_s / imgs
<< " s/img, total read img time: " << total_imread_time_s
<< " s, average read img time: " << total_imread_time_s / imgs
<< " s, batch_size = " << FLAGS_batch_size << std::endl;
return 0;
}
......@@ -62,11 +62,7 @@ int main(int argc, char** argv) {
FLAGS_gpu_id,
FLAGS_key,
FLAGS_use_ir_optim);
double total_running_time_s = 0.0;
double total_imread_time_s = 0.0;
int imgs = 1;
auto colormap = PaddleX::GenerateColorMap(model.labels.size());
// 进行预测
if (FLAGS_image_list != "") {
std::ifstream inf(FLAGS_image_list);
......@@ -81,7 +77,6 @@ int main(int argc, char** argv) {
}
imgs = image_paths.size();
for (int i = 0; i < image_paths.size(); i += FLAGS_batch_size) {
auto start = system_clock::now();
int im_vec_size =
std::min(static_cast<int>(image_paths.size()), i + FLAGS_batch_size);
std::vector<cv::Mat> im_vec(im_vec_size - i);
......@@ -92,21 +87,11 @@ int main(int argc, char** argv) {
for (int j = i; j < im_vec_size; ++j) {
im_vec[j - i] = std::move(cv::imread(image_paths[j], 1));
}
auto imread_end = system_clock::now();
model.predict(im_vec, &results, thread_num);
auto imread_duration = duration_cast<microseconds>(imread_end - start);
total_imread_time_s += static_cast<double>(imread_duration.count()) *
microseconds::period::num /
microseconds::period::den;
auto end = system_clock::now();
auto duration = duration_cast<microseconds>(end - start);
total_running_time_s += static_cast<double>(duration.count()) *
microseconds::period::num /
microseconds::period::den;
// 可视化
for (int j = 0; j < im_vec_size - i; ++j) {
cv::Mat vis_img =
PaddleX::Visualize(im_vec[j], results[j], model.labels, colormap);
PaddleX::Visualize(im_vec[j], results[j], model.labels);
std::string save_path =
PaddleX::generate_save_path(FLAGS_save_dir, image_paths[i + j]);
cv::imwrite(save_path, vis_img);
......@@ -114,28 +99,16 @@ int main(int argc, char** argv) {
}
}
} else {
auto start = system_clock::now();
PaddleX::SegResult result;
cv::Mat im = cv::imread(FLAGS_image, 1);
model.predict(im, &result);
auto end = system_clock::now();
auto duration = duration_cast<microseconds>(end - start);
total_running_time_s += static_cast<double>(duration.count()) *
microseconds::period::num /
microseconds::period::den;
// 可视化
cv::Mat vis_img = PaddleX::Visualize(im, result, model.labels, colormap);
cv::Mat vis_img = PaddleX::Visualize(im, result, model.labels);
std::string save_path =
PaddleX::generate_save_path(FLAGS_save_dir, FLAGS_image);
cv::imwrite(save_path, vis_img);
result.clear();
std::cout << "Visualized output saved as " << save_path << std::endl;
}
std::cout << "Total running time: " << total_running_time_s
<< " s, average running time: " << total_running_time_s / imgs
<< " s/img, total read img time: " << total_imread_time_s
<< " s, average read img time: " << total_imread_time_s / imgs
<< " s, batch_size = " << FLAGS_batch_size << std::endl;
return 0;
}
......@@ -214,6 +214,12 @@ class Padding : public Transform {
height_ = item["target_size"].as<std::vector<int>>()[1];
}
}
if (item["im_padding_value"].IsDefined()) {
im_value_ = item["im_padding_value"].as<std::vector<float>>();
}
else {
im_value_ = {0, 0, 0};
}
}
virtual bool Run(cv::Mat* im, ImageBlob* data);
......@@ -221,6 +227,7 @@ class Padding : public Transform {
int coarsest_stride_ = -1;
int width_ = 0;
int height_ = 0;
std::vector<float> im_value_;
};
/*
* @brief
......
......@@ -65,13 +65,12 @@ std::vector<int> GenerateColorMap(int num_class);
* @param img: initial image matrix
* @param results: the detection result
* @param labels: label map
* @param colormap: visualization color map
* @param threshold: minimum confidence to display
* @return visualized image matrix
* */
cv::Mat Visualize(const cv::Mat& img,
const DetResult& results,
const std::map<int, std::string>& labels,
const std::vector<int>& colormap,
float threshold = 0.5);
/*
......@@ -81,13 +80,11 @@ cv::Mat Visualize(const cv::Mat& img,
* @param img: initial image matrix
* @param results: the detection result
* @param labels: label map
* @param colormap: visualization color map
* @return visualized image matrix
* */
cv::Mat Visualize(const cv::Mat& img,
const SegResult& result,
const std::map<int, std::string>& labels,
const std::vector<int>& colormap);
const std::map<int, std::string>& labels);
/*
* @brief
......
......@@ -110,8 +110,9 @@ bool Padding::Run(cv::Mat* im, ImageBlob* data) {
<< ", but they should be greater than 0." << std::endl;
return false;
}
cv::Scalar value = cv::Scalar(im_value_[0], im_value_[1], im_value_[2]);
cv::copyMakeBorder(
*im, *im, 0, padding_h, 0, padding_w, cv::BORDER_CONSTANT, cv::Scalar(0));
*im, *im, 0, padding_h, 0, padding_w, cv::BORDER_CONSTANT, value);
data->new_im_size_[0] = im->rows;
data->new_im_size_[1] = im->cols;
return true;
......
......@@ -34,8 +34,8 @@ std::vector<int> GenerateColorMap(int num_class) {
cv::Mat Visualize(const cv::Mat& img,
const DetResult& result,
const std::map<int, std::string>& labels,
const std::vector<int>& colormap,
float threshold) {
auto colormap = GenerateColorMap(labels.size());
cv::Mat vis_img = img.clone();
auto boxes = result.boxes;
for (int i = 0; i < boxes.size(); ++i) {
......@@ -107,8 +107,8 @@ cv::Mat Visualize(const cv::Mat& img,
cv::Mat Visualize(const cv::Mat& img,
const SegResult& result,
const std::map<int, std::string>& labels,
const std::vector<int>& colormap) {
const std::map<int, std::string>& labels) {
auto colormap = GenerateColorMap(labels.size());
std::vector<uint8_t> label_map(result.label_map.data.begin(),
result.label_map.data.end());
cv::Mat mask(result.label_map.shape[0],
......
......@@ -5,20 +5,21 @@ PaddleX的安卓端部署由PaddleLite实现,部署的流程如下,首先将
> PaddleX --> Inference Model --> PaddleLite Opt --> PaddleLite Inference
文章简介:
- step1: 介绍如何将PaddleX导出为inference model
- step2: 使用PaddleLite的OPT模块对模型进行优化
- step3: 介绍了基于MobileNetv2的安卓demo,以及PaddleX Android SDK
- 1.介绍如何将PaddleX导出为inference model
- 2.使用PaddleLite的OPT模块对模型进行优化
- 3.介绍基于PaddleX Android SDK的安卓demo,以及如何快速部署训练好的模型
- 4.介绍PaddleX Android SDK和二次开发
## step 1. 将PaddleX模型导出为inference模型
## 1. 将PaddleX模型导出为inference模型
参考[导出inference模型](../export_model.md)将模型导出为inference格式模型。
## step 2. 将inference模型优化为PaddleLite模型
## 2. 将inference模型优化为PaddleLite模型
目前提供了两种方法将Paddle模型优化为PaddleLite模型:
- 1.python脚本优化模型,简单上手,目前支持最新的PaddleLite 2.6.1版本
- 2.bin文件优化模型(linux),支持develop版本(Commit Id:11cbd50e),适用于部署`DeepLab模型`的用户。
- 2.bin文件优化模型(linux),支持develop版本(Commit Id:11cbd50e),适用于部署`DeepLab模型``Unet模型`的用户。
### 2.1 使用python脚本优化模型
......@@ -45,9 +46,19 @@ python export_lite.py --model_dir /path/to/inference_model --save_file /path/to/
--optimize_out_type=naive_buffer \
--optimize_out=model_output_name
```
| 参数 | 说明 |
| ---- | ---- |
| --model_file | 导出inference模型中包含的网络结构文件:`__model__`所在的路径|
| --param_file | 导出inference模型中包含的参数文件:`__params__`所在的路径|
| --valid_targets |指定模型可执行的backend,这里请指定为`arm`|
| --optimize_out_type | 输出模型类型,目前支持两种类型:protobuf和naive_buffer,其中naive_buffer是一种更轻量级的序列化/反序列化,这里请指定为`naive_buffer`|
详细的使用方法和参数含义请参考: [使用opt转化模型](https://paddle-lite.readthedocs.io/zh/latest/user_guides/opt/opt_bin.html)
## step 3. 移动端(Android)预测
## 3. 移动端(Android)Demo
PaddleX提供了一个基于Mobilenetv2模型和PaddleX Android SDK的安卓demo,可供用户体验,该demo位于`/PaddleX/deploy/lite/android/demo`,可直接导入Android Studio后运行,并支持用户替换其他PaddleX导出的检测或分割模型进行预测。
### 3.1 要求
......@@ -56,21 +67,25 @@ python export_lite.py --model_dir /path/to/inference_model --save_file /path/to/
### 3.2 分类Demo
#### 3.2.1 导入工程
#### 3.2.1 导入工程并运行
- 打开Android Studio,在"Welcome to Android Studio"窗口点击"Open an existing Android Studio project",在弹出的路径选择窗口中进入`/PaddleX/deploy/lite/android/demo`目录,然后点击右下角的"Open"按钮,导入工程;
- 通过USB连接Android手机或开发板;
- 载入工程后,点击菜单栏的Run->Run 'App'按钮,在弹出的"Select Deployment Target"窗口选择已经连接的Android设备,然后点击"OK"按钮;
- 运行成功后,Android设备将加载一个名为PaddleX Demo的App,默认会加载一个测试图片,同时还支持拍照和从图库选择照片进行预测;
**注意**:在工程构建的过程中会远程下载Mobilenetv2模型、yml配置文件、测试的图片,以及PaddleX Android SDK。
#### 3.2.2 自定义模型
### 3.3 部署自定义模型
首先根据step1~step2描述,准备好Lite模型(.nb文件)和yml配置文件(注意:导出Lite模型时需指定--place=arm),然后在Android Studio的project视图中:
该demo还支持用户自定义模型来进行预测,可帮助用户快速验证自己训练好的模型,首先我们已经根据step1~step2描述,准备好了Lite模型(.nb文件)和yml配置文件(注意:导出Lite模型时需指定--place=arm),然后在Android Studio的project视图中:
- 将paddlex.nb文件拷贝到`/src/main/assets/model/`目录下。
- 将model.yml文件拷贝到`/src/main/assets/config/`目录下。
- 根据需要,修改文件`/src/main/res/values/strings.xml`中的`MODEL_PATH_DEFAULT``YAML_PATH_DEFAULT`指定的路径。
- 将.nb文件拷贝到`/src/main/assets/model/`目录下, 根据.nb文件的名字,修改文件`/src/main/res/values/strings.xml`中的`MODEL_PATH_DEFAULT`
- 将.yml文件拷贝到`/src/main/assets/config/`目录下,根据.yml文件的名字,修改文件`/src/main/res/values/strings.xml`中的`YAML_PATH_DEFAULT`
- 可根据需要替换测试图片,将图片拷贝到`/src/main/assets/images/`目录下,根据图片文件的名字,修改文件`/src/main/res/values/strings.xml`中的`IMAGE_PATH_DEFAULT`
- 点击菜单栏的Run->Run 'App'按钮,在弹出的"Select Deployment Target"窗口选择已经连接的Android设备,然后点击"OK"按钮;
### 3.3 PaddleX Android SDK介绍
## 4. PaddleX Android SDK和二次开发
PaddleX Android SDK是PaddleX基于Paddle-Lite开发的安卓端AI推理工具,以PaddleX导出的Yaml配置文件为接口,针对不同的模型实现图片的预处理,后处理,并进行可视化,开发者可集成到业务中。
该SDK自底向上主要包括:Paddle-Lite推理引擎层,Paddle-Lite接口层以及PaddleX业务层。
......@@ -81,7 +96,7 @@ PaddleX Android SDK是PaddleX基于Paddle-Lite开发的安卓端AI推理工具
![架构](../images/paddlex_android_sdk_framework.jpg)
#### 3.3.1 SDK安装
### 4.1 SDK安装
首先下载并解压[PaddleX Android SDK](https://bj.bcebos.com/paddlex/deploy/lite/paddlex_lite_11cbd50e.tar.gz),得到paddlex.aar文件,将拷贝到android工程目录app/libs/下面,然后为app的build.gradle添加依赖:
......@@ -92,7 +107,7 @@ dependencies {
```
#### 3.3.2 SDK使用用例
### 4.2 SDK使用用例
```
import com.baidu.paddlex.Predictor;
import com.baidu.paddlex.config.ConfigParser;
......@@ -132,7 +147,7 @@ if (configParser.getModelType().equalsIgnoreCase("segmenter")) {
ClsResult clsResult = predictor.getClsResult();
}
```
#### 3.3.3 Result成员变量
### 4.3 Result成员变量
**注意**:Result所有的成员变量以java bean的方式获取。
......@@ -179,12 +194,12 @@ com.baidu.paddlex.postprocess.SegResult
com.baidu.paddlex.postprocess.SegResult.Mask
```
##### Fields
> * **scoreData** (float[]): 模型预测在各个类别的置信度,长度为numClass$\times\$H$\times\$W
> * **scoreData** (float[]): 模型预测在各个类别的置信度,长度为: 1 * numClass * H * W
> * **scoreShape** (long[4]): scoreData的shape信息,[1,numClass,H,W]
> * **labelData** (long[]): 模型预测置信度最高的label,长度为`H$\times\$W$\times\$1
> * **labelData** (long[]): 模型预测置信度最高的label,长度为: 1 * H * W * 1
> * **labelShape** (long[4]): labelData的shape信息,[1,H,W,1]
#### 3.3.4 SDK二次开发
### 4.4 SDK二次开发
- 打开Android Studio新建项目(或加载已有项目)。点击菜单File->New->Import Module,导入工程`/PaddleX/deploy/lite/android/sdk`, Project视图会新增名为sdk的module
- 在app的build.grade里面添加依赖:
......
......@@ -27,6 +27,21 @@
|humanseg_mobile_quant | 1.6M | 24.93ms |
执行以下脚本下载全部的预训练模型:
* 下载PaddleX源码:
```bash
git clone https://github.com/PaddlePaddle/PaddleX
```
* 下载预训练模型的代码位于`PaddleX/examples/human_segmentation`,进入该目录:
```bash
cd PaddleX/examples/human_segmentation
```
* 执行下载
```bash
python pretrain_weights/download_pretrain_weights.py
```
......@@ -35,6 +50,8 @@ python pretrain_weights/download_pretrain_weights.py
[supervise.ly](https://supervise.ly/)发布了人像分割数据集**Supervisely Persons**, 本案例从中随机抽取一小部分数据并转化成PaddleX可直接加载的数据格式,运行以下代码可下载该数据、以及手机前置摄像头拍摄的人像测试视频`video_test.mp4`.
* 下载测试数据的代码位于`PaddleX/xamples/human_segmentation`,进入该目录并执行下载:
```bash
python data/download_data.py
```
......@@ -49,9 +66,21 @@ python data/download_data.py
安装的相关问题参考[PaddleX安装](../../docs/install.md)
* 下载PaddleX源码:
```bash
git clone https://github.com/PaddlePaddle/PaddleX
```
* 视频流人像分割和背景替换的执行文件均位于`PaddleX/examples/human_segmentation`,进入该目录:
```bash
cd PaddleX/examples/human_segmentation
```
### 光流跟踪辅助的视频流人像分割
本案例将DIS(Dense Inverse Search-basedmethod)光流跟踪算法的预测结果与PaddleX的分割结果进行融合,以此改善视频流人像分割的效果。运行以下代码进行体验:
本案例将DIS(Dense Inverse Search-basedmethod)光流跟踪算法的预测结果与PaddleX的分割结果进行融合,以此改善视频流人像分割的效果。运行以下代码进行体验,以下代码位于`PaddleX/xamples/human_segmentation`
* 通过电脑摄像头进行实时分割处理
......@@ -70,7 +99,7 @@ python video_infer.py --model_dir pretrain_weights/humanseg_mobile_inference --v
### 人像背景替换
本案例还实现了人像背景替换功能,根据所选背景对人像的背景画面进行替换,背景可以是一张图片,也可以是一段视频。
本案例还实现了人像背景替换功能,根据所选背景对人像的背景画面进行替换,背景可以是一张图片,也可以是一段视频。人像背景替换的代码位于`PaddleX/xamples/human_segmentation`,进入该目录并执行:
* 通过电脑摄像头进行实时背景替换处理, 通过'--background_video_path'传入背景视频
```bash
......@@ -105,6 +134,18 @@ python bg_replace.py --model_dir pretrain_weights/humanseg_mobile_inference --im
安装的相关问题参考[PaddleX安装](../../docs/install.md)
* 下载PaddleX源码:
```bash
git clone https://github.com/PaddlePaddle/PaddleX
```
* 人像分割训练、评估、预测、模型导出、离线量化的执行文件均位于`PaddleX/examples/human_segmentation`,进入该目录:
```bash
cd PaddleX/examples/human_segmentation
```
### 模型训练
使用下述命令进行基于预训练模型的模型训练,请确保选用的模型结构`model_type`与模型参数`pretrain_weights`匹配。如果不需要本案例提供的测试数据,可更换数据、选择合适的模型并调整训练参数。
......@@ -203,3 +244,62 @@ python quant_offline.py --model_dir output/best_model \
* `--image_shape`: 网络输入图像大小(w, h)
## Paddle-Lite移动端部署
本案例将人像分割模型在移动端进行部署,部署流程展示如下,通用的移动端部署流程参见[PaddleLite移动端部署](../../docs/deploy/paddlelite/android.md)
### 1. 将PaddleX模型导出为inference模型
本案例使用humanseg_mobile_quant预训练模型,该模型已经是inference模型,不需要再执行模型导出步骤。如果不使用预训练模型,则执行上一章节`模型训练`中的`模型导出`将自己训练的模型导出为inference格式。
### 2. 将inference模型优化为PaddleLite模型
下载并解压 [模型优化工具opt](https://bj.bcebos.com/paddlex/deploy/lite/model_optimize_tool_11cbd50e.tar.gz),进入模型优化工具opt所在路径后,执行以下命令:
``` bash
./opt --model_file=<model_path> \
--param_file=<param_path> \
--valid_targets=arm \
--optimize_out_type=naive_buffer \
--optimize_out=model_output_name
```
| 参数 | 说明 |
| ---- | ---- |
| --model_file | 导出inference模型中包含的网络结构文件:`__model__`所在的路径|
| --param_file | 导出inference模型中包含的参数文件:`__params__`所在的路径|
| --valid_targets |指定模型可执行的backend,这里请指定为`arm`|
| --optimize_out_type | 输出模型类型,目前支持两种类型:protobuf和naive_buffer,其中naive_buffer是一种更轻量级的序列化/反序列化,这里请指定为`naive_buffer`|
| --optimize_out | 输出模型的名称 |
更详细的使用方法和参数含义请参考: [使用opt转化模型](https://paddle-lite.readthedocs.io/zh/latest/user_guides/opt/opt_bin.html)
### 3. 移动端预测
PaddleX提供了基于PaddleX Android SDK的安卓demo,可供用户体验图像分类、目标检测、实例分割和语义分割,该demo位于`PaddleX/deploy/lite/android/demo`,用户将模型、配置文件和测试图片拷贝至该demo下进行预测。
#### 3.1 前置依赖
* Android Studio 3.4
* Android手机或开发板
#### 3.2 拷贝模型、配置文件和测试图片
* 将Lite模型(.nb文件)拷贝到`PaddleX/deploy/lite/android/demo/app/src/main/assets/model/`目录下, 根据.nb文件的名字,修改文件`PaddleX/deploy/lite/android/demo/app/src/main/res/values/strings.xml`中的`MODEL_PATH_DEFAULT`
* 将配置文件(.yml文件)拷贝到`PaddleX/deploy/lite/android/demo/app/src/main/assets/config/`目录下,根据.yml文件的名字,修改文件`PaddleX/deploy/lite/android/demo/app/src/main/res/values/strings.xml`中的`YAML_PATH_DEFAULT`
* 将测试图片拷贝到`PaddleX/deploy/lite/android/demo/app/src/main/assets/images/`目录下,根据图片文件的名字,修改文件`PaddleX/deploy/lite/android/demo/app/src/main/res/values/strings.xml`中的`IMAGE_PATH_DEFAULT`
#### 3.3 导入工程并运行
* 打开Android Studio,在"Welcome to Android Studio"窗口点击"Open an existing Android Studio project",在弹出的路径选择窗口中进入`PaddleX/deploy/lite/android/demo`目录,然后点击右下角的"Open"按钮,导入工程;
* 通过USB连接Android手机或开发板;
* 工程编译完成后,点击菜单栏的Run->Run 'App'按钮,在弹出的"Select Deployment Target"窗口选择已经连接的Android设备,然后点击"OK"按钮;
* 运行成功后,Android设备将加载一个名为PaddleX Demo的App,默认会加载一个测试图片,同时还支持拍照和从图库选择照片进行预测。
测试图片及其分割结果如下所示:
![](./images/beauty.png)
文件已添加
## <a name="2">PaddleX GUI安装</a>
PaddleX GUI是提升项目开发效率的核心模块,开发者可快速完成深度学习模型全流程开发。我们诚挚地邀请您前往 [官网](https://www.paddlepaddle.org.cn/paddle/paddleX)下载试用PaddleX GUI可视化前端,并获得您宝贵的意见或开源项目贡献。
#### <a name="1">安装推荐环境</a>
* **操作系统**
* Windows7/8/10(推荐Windows 10);
* Mac OS 10.13+;
* Ubuntu 18.04+;
***注:处理器需为x86_64架构,支持MKL。***
* **训练硬件**
* **GPU**(仅Windows及Linux系统):
推荐使用支持CUDA的NVIDIA显卡,例如:GTX 1070+以上性能的显卡;
Windows系统X86_64驱动版本>=411.31;
Linux系统X86_64驱动版本>=410.48;
显存8G以上;
* **CPU**
PaddleX当前支持您用本地CPU进行训练,但推荐使用GPU以获得更好的开发体验。
* **内存**:建议8G以上
* **硬盘空间**:建议SSD剩余空间1T以上(非必须)
***注:PaddleX在Windows及Mac OS系统只支持单卡模型。Windows系统暂不支持NCCL。***
## FAQ
1. **为什么训练速度这么慢?**
PaddleX完全采用您本地的硬件进行计算,深度学习任务确实对算力要求较高,为了使您能快速体验应用PaddleX进行开发,我们适配了CPU硬件,但强烈建议您使用GPU以提升训练速度和开发体验。
2. **我可以在服务器或云平台上部署PaddleX么?**
PaddleX GUI是一个适配本地单机安装的客户端,无法在服务器上直接进行部署,您可以直接使用PaddleX API,或采用飞桨核心框架进行服务器上的部署。如果您希望使用公有算力,强烈建议您尝试飞桨产品系列中的 [EasyDL](https://ai.baidu.com/easydl/)[AI Studio](https://aistudio.baidu.com/aistudio/index)进行开发。
3. **PaddleX支持EasyData标注的数据吗?**
支持,PaddleX可顺畅读取EasyData标注的数据。但当前版本的PaddleX GUI暂时无法支持直接导入EasyData数据格式,您可以参照文档,将[数据集进行转换](https://paddlex.readthedocs.io/zh_CN/latest/appendix/how_to_convert_dataset.html)再导入PaddleX GUI进行后续开发。
同时,我们也在紧密开发PaddleX GUI可直接导入EasyData数据格式的功能。
4. **为什么模型裁剪分析耗时这么长?**
模型裁剪分析过程是对模型各卷积层的敏感度信息进行分析,根据各参数对模型效果的影响进行不同比例的裁剪。此过程需要重复多次直至FLOPS满足要求,最后再进行精调训练获得最终裁剪后的模型,因此耗时较长。有关模型裁剪的原理,可参见文档[剪裁原理介绍](https://paddlepaddle.github.io/PaddleSlim/algo/algo.html#2-%E5%8D%B7%E7%A7%AF%E6%A0%B8%E5%89%AA%E8%A3%81%E5%8E%9F%E7%90%86)
5. **如何调用后端代码?**
PaddleX 团队为您整理了相关的API接口文档,方便您学习和使用。具体请参见[PaddleX API说明文档](https://paddlex.readthedocs.io/zh_CN/latest/apis/index.html)
**如果您有任何问题或建议,欢迎以issue的形式,或加入PaddleX官方QQ群(1045148026)直接反馈您的问题和需求**
![](/Users/lvxueying/Documents/LaraPaddleX/docs/paddlex_gui/images/QR.jpg)
\ No newline at end of file
# PaddleX GUI使用教程
**第一步:准备数据**
在开始模型训练前,您需要根据不同的任务类型,将数据标注为相应的格式。目前PaddleX支持【图像分类】、【目标检测】、【语义分割】、【实例分割】四种任务类型。不同类型任务的数据处理方式可查看[数据标注方式](https://paddlex.readthedocs.io/zh_CN/latest/appendix/datasets.html)
**第二步:导入我的数据集**
①数据标注完成后,您需要根据不同的任务,将数据和标注文件,按照客户端提示更名并保存到正确的文件中。
②在客户端新建数据集,选择与数据集匹配的任务类型,并选择数据集对应的路径,将数据集导入。
![](images/datasets1.jpg)
③选定导入数据集后,客户端会自动校验数据及标注文件是否合规,校验成功后,您可根据实际需求,将数据集按比例划分为训练集、验证集、测试集。
④您可在「数据分析」模块按规则预览您标注的数据集,双击单张图片可放大查看。
![](images/dataset2.jpg)
**第三步:创建项目**
① 在完成数据导入后,您可以点击「新建项目」创建一个项目。
② 您可根据实际任务需求选择项目的任务类型,需要注意项目所采用的数据集也带有任务类型属性,两者需要进行匹配。
![](images/project3.jpg)
**第四步:项目开发**
**数据选择**:项目创建完成后,您需要选择已载入客户端并校验后的数据集,并点击下一步,进入参数配置页面。
![](images/project1.jpg)
**参数配置**:主要分为**模型参数****训练参数****优化策略**三部分。您可根据实际需求选择模型结构、骨架网络及对应的训练参数、优化策略,使得任务效果最佳。
![](images/project2.jpg)
参数配置完成后,点击启动训练,模型开始训练并进行效果评估。
**训练可视化**:在训练过程中,您可通过VisualDL查看模型训练过程参数变化、日志详情,及当前最优的训练集和验证集训练指标。模型在训练过程中通过点击"中止训练"随时中止训练过程。
![](images/visualization1.jpg)
模型训练结束后,可选择进入『模型剪裁分析』或者直接进入『模型评估』。
![](images/visualization2.jpg)
**模型裁剪**:如果开发者希望减少模型的体积、计算量,提升模型在设备上的预测性能,可以采用PaddleX提供的模型裁剪策略。裁剪过程将对模型各卷积层的敏感度信息进行分析,根据各参数对模型效果的影响进行不同比例的裁剪,再进行精调训练获得最终裁剪后的模型。
![](images/visualization3.jpg)
**模型评估**:在模型评估页面,您可查看训练后的模型效果。评估方法包括混淆矩阵、精度、召回率等。
![](images/visualization4.jpg)
您还可以选择『数据集切分』时留出的『测试数据集』或从本地文件夹中导入一张/多张图片,将训练后的模型进行测试。根据测试结果,您可决定是否将训练完成的模型保存为预训练模型并进入模型发布页面,或返回先前步骤调整参数配置重新进行训练。
![](images/visualization5.jpg)
**第五步:模型发布**
当模型效果满意后,您可根据实际的生产环境需求,选择将模型发布为需要的版本。
![](images/publish.jpg)
**如果您有任何问题或建议,欢迎以issue的形式,或加入PaddleX官方QQ群(1045148026)直接反馈您的问题和需求**
![](images/QR.jpg)
PaddleX GUI Screen Shot
......@@ -35,6 +35,21 @@
|humanseg_mobile_quant | 1.6M | 24.93ms |
执行以下脚本下载全部的预训练模型:
* 下载PaddleX源码:
```bash
git clone https://github.com/PaddlePaddle/PaddleX
```
* 下载预训练模型的代码位于`PaddleX/examples/human_segmentation`,进入该目录:
```bash
cd PaddleX/examples/human_segmentation
```
* 执行下载
```bash
python pretrain_weights/download_pretrain_weights.py
```
......@@ -43,6 +58,8 @@ python pretrain_weights/download_pretrain_weights.py
[supervise.ly](https://supervise.ly/)发布了人像分割数据集**Supervisely Persons**, 本案例从中随机抽取一小部分数据并转化成PaddleX可直接加载的数据格式,运行以下代码可下载该数据、以及手机前置摄像头拍摄的人像测试视频`video_test.mp4`.
* 下载测试数据的代码位于`PaddleX/xamples/human_segmentation`,进入该目录并执行下载:
```bash
python data/download_data.py
```
......@@ -57,9 +74,21 @@ python data/download_data.py
安装的相关问题参考[PaddleX安装](../../docs/install.md)
* 下载PaddleX源码:
```bash
git clone https://github.com/PaddlePaddle/PaddleX
```
* 视频流人像分割和背景替换的执行文件均位于`PaddleX/examples/human_segmentation`,进入该目录:
```bash
cd PaddleX/examples/human_segmentation
```
### 光流跟踪辅助的视频流人像分割
本案例将DIS(Dense Inverse Search-basedmethod)光流跟踪算法的预测结果与PaddleX的分割结果进行融合,以此改善视频流人像分割的效果。运行以下代码进行体验:
本案例将DIS(Dense Inverse Search-basedmethod)光流跟踪算法的预测结果与PaddleX的分割结果进行融合,以此改善视频流人像分割的效果。运行以下代码进行体验,以下代码位于`PaddleX/xamples/human_segmentation`
* 通过电脑摄像头进行实时分割处理
......@@ -78,7 +107,7 @@ python video_infer.py --model_dir pretrain_weights/humanseg_mobile_inference --v
### 人像背景替换
本案例还实现了人像背景替换功能,根据所选背景对人像的背景画面进行替换,背景可以是一张图片,也可以是一段视频。
本案例还实现了人像背景替换功能,根据所选背景对人像的背景画面进行替换,背景可以是一张图片,也可以是一段视频。人像背景替换的代码位于`PaddleX/xamples/human_segmentation`,进入该目录并执行:
* 通过电脑摄像头进行实时背景替换处理, 通过'--background_video_path'传入背景视频
```bash
......@@ -115,6 +144,18 @@ python bg_replace.py --model_dir pretrain_weights/humanseg_mobile_inference --im
安装的相关问题参考[PaddleX安装](../../docs/install.md)
* 下载PaddleX源码:
```bash
git clone https://github.com/PaddlePaddle/PaddleX
```
* 人像分割训练、评估、预测、模型导出、离线量化的执行文件均位于`PaddleX/examples/human_segmentation`,进入该目录:
```bash
cd PaddleX/examples/human_segmentation
```
### 模型训练
使用下述命令进行基于预训练模型的模型训练,请确保选用的模型结构`model_type`与模型参数`pretrain_weights`匹配。如果不需要本案例提供的测试数据,可更换数据、选择合适的模型并调整训练参数。
......@@ -213,3 +254,62 @@ python quant_offline.py --model_dir output/best_model \
* `--image_shape`: 网络输入图像大小(w, h)
## <h2 id="4">Paddle-Lite移动端部署</h2>
本案例将人像分割模型在移动端进行部署,部署流程展示如下,通用的移动端部署流程参见[PaddleLite移动端部署](../../docs/deploy/paddlelite/android.md)
### 1. 将PaddleX模型导出为inference模型
本案例使用humanseg_mobile_quant预训练模型,该模型已经是inference模型,不需要再执行模型导出步骤。如果不使用预训练模型,则执行上一章节`模型训练`中的`模型导出`将自己训练的模型导出为inference格式。
### 2. 将inference模型优化为PaddleLite模型
下载并解压 [模型优化工具opt](https://bj.bcebos.com/paddlex/deploy/lite/model_optimize_tool_11cbd50e.tar.gz),进入模型优化工具opt所在路径后,执行以下命令:
``` bash
./opt --model_file=<model_path> \
--param_file=<param_path> \
--valid_targets=arm \
--optimize_out_type=naive_buffer \
--optimize_out=model_output_name
```
| 参数 | 说明 |
| ---- | ---- |
| --model_file | 导出inference模型中包含的网络结构文件:`__model__`所在的路径|
| --param_file | 导出inference模型中包含的参数文件:`__params__`所在的路径|
| --valid_targets |指定模型可执行的backend,这里请指定为`arm`|
| --optimize_out_type | 输出模型类型,目前支持两种类型:protobuf和naive_buffer,其中naive_buffer是一种更轻量级的序列化/反序列化,这里请指定为`naive_buffer`|
| --optimize_out | 输出模型的名称 |
更详细的使用方法和参数含义请参考: [使用opt转化模型](https://paddle-lite.readthedocs.io/zh/latest/user_guides/opt/opt_bin.html)
### 3. 移动端预测
PaddleX提供了基于PaddleX Android SDK的安卓demo,可供用户体验图像分类、目标检测、实例分割和语义分割,该demo位于`PaddleX/deploy/lite/android/demo`,用户将模型、配置文件和测试图片拷贝至该demo下进行预测。
#### 3.1 前置依赖
* Android Studio 3.4
* Android手机或开发板
#### 3.2 拷贝模型、配置文件和测试图片
* 将Lite模型(.nb文件)拷贝到`PaddleX/deploy/lite/android/demo/app/src/main/assets/model/`目录下, 根据.nb文件的名字,修改文件`PaddleX/deploy/lite/android/demo/app/src/main/res/values/strings.xml`中的`MODEL_PATH_DEFAULT`
* 将配置文件(.yml文件)拷贝到`PaddleX/deploy/lite/android/demo/app/src/main/assets/config/`目录下,根据.yml文件的名字,修改文件`PaddleX/deploy/lite/android/demo/app/src/main/res/values/strings.xml`中的`YAML_PATH_DEFAULT`
* 将测试图片拷贝到`PaddleX/deploy/lite/android/demo/app/src/main/assets/images/`目录下,根据图片文件的名字,修改文件`PaddleX/deploy/lite/android/demo/app/src/main/res/values/strings.xml`中的`IMAGE_PATH_DEFAULT`
#### 3.3 导入工程并运行
* 打开Android Studio,在"Welcome to Android Studio"窗口点击"Open an existing Android Studio project",在弹出的路径选择窗口中进入`PaddleX/deploy/lite/android/demo`目录,然后点击右下角的"Open"按钮,导入工程;
* 通过USB连接Android手机或开发板;
* 工程编译完成后,点击菜单栏的Run->Run 'App'按钮,在弹出的"Select Deployment Target"窗口选择已经连接的Android设备,然后点击"OK"按钮;
* 运行成功后,Android设备将加载一个名为PaddleX Demo的App,默认会加载一个测试图片,同时还支持拍照和从图库选择照片进行预测。
测试图片及其分割结果如下所示:
![](./data/beauty.png)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册