浏览代码

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

will-jl944 4 年之前
父节点
当前提交
37a2ce625e
共有 37 个文件被更改,包括 1575 次插入285 次删除
  1. 106 71
      README.md
  2. 0 171
      README_cn.md
  3. 145 0
      README_en.md
  4. 144 0
      docs/Resful_API/docs/readme.md
  5. 二进制
      docs/Resful_API/images/1.png
  6. 二进制
      docs/Resful_API/images/10.png
  7. 二进制
      docs/Resful_API/images/2.5.png
  8. 二进制
      docs/Resful_API/images/2.6.png
  9. 二进制
      docs/Resful_API/images/2.png
  10. 二进制
      docs/Resful_API/images/3.png
  11. 二进制
      docs/Resful_API/images/4.png
  12. 二进制
      docs/Resful_API/images/5.5.png
  13. 二进制
      docs/Resful_API/images/5.png
  14. 二进制
      docs/Resful_API/images/6.png
  15. 二进制
      docs/Resful_API/images/7.png
  16. 二进制
      docs/Resful_API/images/8.png
  17. 二进制
      docs/Resful_API/images/9.png
  18. 46 10
      dygraph/README.md
  19. 7 1
      dygraph/deploy/cpp/model_deploy/common/include/transforms.h
  20. 22 4
      dygraph/deploy/cpp/model_deploy/common/src/transforms.cpp
  21. 51 2
      dygraph/deploy/cpp/model_deploy/paddlex/include/x_standard_config.h
  22. 5 1
      dygraph/deploy/cpp/model_deploy/paddlex/src/x_model.cpp
  23. 3 1
      dygraph/examples/README.md
  24. 321 0
      dygraph/examples/meter_reader/README.md
  25. 二进制
      dygraph/examples/meter_reader/images/MeterReader_Architecture.jpg
  26. 二进制
      dygraph/examples/meter_reader/images/det_data.png
  27. 二进制
      dygraph/examples/meter_reader/images/scene_introduce.jpg
  28. 二进制
      dygraph/examples/meter_reader/images/seg_data.png
  29. 二进制
      dygraph/examples/meter_reader/images/visualize_1624716128584.jpg
  30. 598 0
      dygraph/examples/meter_reader/reader_infer.py
  31. 55 0
      dygraph/examples/meter_reader/train_detection.py
  32. 54 0
      dygraph/examples/meter_reader/train_segmentation.py
  33. 2 0
      dygraph/paddlex/cv/models/base.py
  34. 5 2
      dygraph/paddlex/cv/models/classifier.py
  35. 8 20
      dygraph/paddlex/cv/models/detector.py
  36. 2 1
      dygraph/paddlex/cv/models/segmenter.py
  37. 1 1
      dygraph/paddlex/cv/transforms/operators.py

+ 106 - 71
README.md

@@ -1,5 +1,4 @@
-[简体中文](./README_cn.md) | English
-
+简体中文| [English](./README.md)
 
 
 
@@ -7,139 +6,175 @@
 <p align="center">
   <img src="./docs/gui/images/paddlex.png" width="360" height ="55" alt="PaddleX" align="middle" />
 </p>
-
-
-<p align= "center"> PaddleX -- PaddlePaddle End-to-End Development Toolkit,
-  enables developers to implement real industry projects in a low-code form quickly </p>
+ <p align= "center"> PaddleX -- 飞桨全流程开发工具,以低代码的形式支持开发者快速实现产业实际项目落地 </p>
 
 [![License](https://img.shields.io/badge/license-Apache%202-red.svg)](LICENSE) [![Version](https://img.shields.io/github/release/PaddlePaddle/PaddleX.svg)](https://github.com/PaddlePaddle/PaddleX/releases) ![python version](https://img.shields.io/badge/python-3.6+-orange.svg) ![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 dynamic graph mode is ready! Static graph mode is set as default and dynamic graph code base is in [dygraph](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph). If you want to use static graph mode, the version 1.3.11 can be installed by pip. The version 2.0.0rc0 corresponds to the dynamic graph mode.
+## PaddleX全面升级动态图,动态图版本位于[dygraph](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph)中,欢迎用户点击体验
 
 
-:hugs:  PaddleX integrated the abilities of **Image classification**, **Object detection**, **Semantic segmentation**, and **Instance segmentation** in the Paddle CV toolkits, and get through the whole-process development from **Data preparation** and **Model training and optimization** to **Multi-end deployment**. At the same time, PaddleX provides **Succinct APIs** and a **Graphical User Interface**. Developers can quickly complete the end-to-end process development of the Paddle in a form of **low-code**  without installing different libraries.
+## :heart: 重磅功能升级提醒
+* 全新发布Manufacture SDK,提供工业级多端多平台部署加速的预编译飞桨部署开发包(SDK),通过配置业务逻辑流程文件即可以低代码方式快速完成推理部署,[欢迎体验](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/deploy/cpp)。
 
-**:factory: PaddleX** has been validated in a dozen of industry application scenarios such as **Quality Inspection**, **Security**, **Patrol Inspection**, **Remote Sensing**, **Retail**,  **Medical** etc.. In addition, it **provides a wealth of case practice tutorials**, to help developer could apply to actual cases easily.
+* PaddleX部署全面升级,支持飞桨视觉套件PaddleDetection、PaddleClas、PaddleSeg、PaddleX的统一部署能力,[欢迎体验](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/deploy/cpp)。
 
+:hugs: PaddleX 集成飞桨智能视觉领域**图像分类**、**目标检测**、**语义分割**、**实例分割**任务能力,将深度学习开发全流程从**数据准备**、**模型训练与优化**到**多端部署**端到端打通,并提供**统一任务API接口**及**图形化开发界面Demo**。开发者无需分别安装不同套件,以**低代码**的形式即可快速完成飞桨全流程开发。
 
+:factory: **PaddleX** 经过**质检**、**安防**、**巡检**、**遥感**、**零售**、**医疗**等十多个行业实际应用场景验证,沉淀产业实际经验,**并提供丰富的案例实践教程**,全程助力开发者产业实践落地。
 
-:heart: **You can go to [Complete PaddleX Online Documentation Contents](https://paddlex.readthedocs.io/zh_CN/develop_en/index.html) for complete tutorial with the format of *Read the Doc* and better reading experience​** :heart:
 
 
+:heart:**您可以前往  [完整PaddleX在线使用文档目录](https://paddlex.readthedocs.io/zh_CN/develop/index.html)  查看完整*Read the Doc* 格式的文档,获得更好的阅读体验**:heart:
 
-![](./docs/gui/images/paddlexoverview_en.jpg)
 
 
+![](./docs/gui/images/paddlexoverview.png)
 
-## Installation
 
-**PaddleX has two development modes to meet different needs of users:**
 
-1.**Python development mode:**
+## 安装
 
-The design of PaddleX Python API taking into account of comprehensive functions, development flexibility, and integration convenience, giving developers the smoothest deep learning development experience.
+**PaddleX提供三种开发模式,满足用户的不同需求:**
 
-**Pre-dependence**
+1. **Python开发模式:**
 
+   通过简洁易懂的Python API,在兼顾功能全面性、开发灵活性、集成方便性的基础上,给开发者最流畅的深度学习开发体验。<br>
+
+  **前置依赖**
 > - paddlepaddle >= 1.8.4
 > - python >= 3.6
 > - cython
 > - pycocotools
 
-You shuould use command of python3 and pip3 instead if you have python2 installed.
-
 ```
 pip install paddlex -i https://mirror.baidu.com/pypi/simple
 ```
-Please refer to the [PaddleX installation](https://paddlex.readthedocs.io/zh_CN/develop/install.html) for detailed installation method.
+详细安装方法请参考[PaddleX安装](https://paddlex.readthedocs.io/zh_CN/develop/install.html)
 
 
-2. **Padlde GUI(Graphical User Interface) mode:**
+2. **Padlde GUI模式:**
 
-It's a all-in-one client enable develops could implement deep learning projects without code.
+   无代码开发的可视化客户端,应用Paddle API实现,使开发者快速进行产业项目验证,并为用户开发自有深度学习软件/应用提供参照。
 
-- Go to [PaddleX Official Website](https://www.paddlepaddle.org.cn/paddle/paddlex) to download the all-in-one client.
+- 前往[PaddleX官网](https://www.paddlepaddle.org.cn/paddle/paddlex),申请下载PaddleX GUI一键绿色安装包。
 
-- Go to [PaddleX GUI tutorial](./docs/gui/how_to_use.md ) for details of using it.
+- 前往[PaddleX GUI使用教程](./docs/gui/how_to_use.md)了解PaddleX GUI使用详情。
 
-- [PaddleX GUI Environment Requirements for Installation](./docs/gui/download.md)
+- [PaddleX GUI安装环境说明](./docs/gui/download.md)
 
+3. **PaddleX Restful:**  
+  使用基于RESTful API开发的GUI与Web Demo实现远程的深度学习全流程开发;同时开发者也可以基于RESTful API开发个性化的可视化界面
+- 前往[PaddleX RESTful API使用教程](./docs/gui/restful/introduction.md)  
 
-## Product Module Description
 
-- **Data preparation**: Compatible with common data protocols such as ImageNet, VOC, COCO, and seamlessly interconnecting with Labelme, Colabeler, and [EasyData intelligent data service platform](https://ai.baidu.com/easydata/), to help developers to quickly complete data preparations.
-- **Data pre-processing and enhancement**: Provides a minimalist image pre-processing and enhancement method--Transforms. Adapts imgaug which is a powerful image enhancement library, so that PaddleX could supports **Hundreds of data enhancement strategies**, which makes developers quickly alleviate the situation of traing with small sample dataset.
-- **Model training**: PaddleX integrates [PaddleClas](https://github.com/PaddlePaddle/PaddleClas), [PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection), and [PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg) etcs. So it provides a large number of selected, industry-proven, high-quality pre-trained models, enabling developers to achieve the industry requirements much more quickly.
-- **Model tuning**: Model-interpretability module and [VisualDL](https://github.com/PaddlePaddle/VisualDL) visual analysis tool are integrated as well. It allows developers to understand the model's feature extraction region and the change of the training process parameters more intuitively , so as to quickly optimize the model.
-- **Multi-End Secure Deployment**: The built-in model compression tool-- [PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim)  and **Model Encryption Deployment Module**, are seamlessly interconnected with native prediction library **Paddle Inference** and Multi-platform high performance deep learning inference engine-- [Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite) , to enable developers to quickly implement multi-end, high-performance, secure deployments of the model.
+## 产品模块说明
 
+- **数据准备**:兼容ImageNet、VOC、COCO等常用数据协议,同时与Labelme、精灵标注助手、[EasyData智能数据服务平台](https://ai.baidu.com/easydata/)等无缝衔接,全方位助力开发者更快完成数据准备工作。
 
+- **数据预处理及增强**:提供极简的图像预处理和增强方法--Transforms,适配imgaug图像增强库,支持**上百种数据增强策略**,是开发者快速缓解小样本数据训练的问题。
 
-## Full Documentation and API Description
+- **模型训练**:集成[PaddleClas](https://github.com/PaddlePaddle/PaddleClas), [PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection), [PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg)视觉开发套件,提供大量精选的、经过产业实践的高质量预训练模型,使开发者更快实现工业级模型效果。
 
-- [Complete PaddleX online documentation contents](https://paddlex.readthedocs.io/zh_CN/develop_en/):heart:
+- **模型调优**:内置模型可解释性模块、[VisualDL](https://github.com/PaddlePaddle/VisualDL)可视化分析工具。使开发者可以更直观的理解模型的特征提取区域、训练过程参数变化,从而快速优化模型。
 
-- [10-Minute Quick Start Tutorial Series](https://paddlex.readthedocs.io/zh_CN/develop/quick_start.html)
-- [Collection of PaddleX Model Training Tutorials](https://paddlex.readthedocs.io/zh_CN/develop/train/index.html)
-- [PaddleX API Interface Description](https://paddlex.readthedocs.io/zh_CN/develop/apis/index.html)
+- **多端安全部署**:内置[PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim)模型压缩工具和**模型加密部署模块**,与飞桨原生预测库Paddle Inference及高性能端侧推理引擎[Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite) 无缝打通,使开发者快速实现模型的多端、高性能、安全部署。
 
-### Examples of Online Projects
 
-To get developers up to speed with the PaddleX API, we've created a complete series of sample tutorials that you can run PaddleX projects online through the **AIStudio** quickly.
 
-- [PaddleX Quick Start - CV Model Training](https://aistudio.baidu.com/aistudio/projectdetail/450925)
-- [PaddleX Quick Start - MobileNetV3-ssld Cosmetics Classification](https://aistudio.baidu.com/aistudio/projectdetail/450220)
-- [PaddleX Quick Start - Faster-RCNN AI Bug Recognition](https://aistudio.baidu.com/aistudio/projectdetail/439888)
-- [PaddleX Quick Start - DeepLabv3+ Semantic Segmentation](https://aistudio.baidu.com/aistudio/projectdetail/440197)
+## 完整使用文档及API说明
 
+- [完整PaddleX在线使用文档目录](https://paddlex.readthedocs.io/zh_CN/develop/index.html):heart:
 
+- [10分钟快速上手系列教程](https://paddlex.readthedocs.io/zh_CN/develop/quick_start.html)
+- [PaddleX模型训练教程集合](https://paddlex.readthedocs.io/zh_CN/develop/train/index.html)
+- [PaddleX API接口说明](https://paddlex.readthedocs.io/zh_CN/develop/apis/index.html)
+- [PaddleX RESTful API说明](https://paddlex.readthedocs.io/zh_CN/develop/gui/restful/introduction.html)
 
-## Full Process Industry Applications:star:
+### 在线项目示例
 
-(continue to be updated)
+为了使开发者更快掌握PaddleX API,我们创建了一系列完整的示例教程,您可通过AIStudio一站式开发平台,快速在线运行PaddleX的项目。
 
-* Industrial inspections:
-  - [Industrial Meter Readings](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/meter_reader.html)
-* [Industrial quality control](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/industrial_quality_inspection/README.html)
-* Satellite Image Understanding:
-  * [RGB Satellite Image Segmentation](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/remote_sensing.html)
-  * [Multi-Channel Satellite Image Segmentation](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/multi-channel_remote_sensing/README.html)
-  * [Land Parcel Change Detection](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/change_detection.html)
-* [Portrait Segmentation](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/human_segmentation.html)
-* Multi-platform Deployment with Encryption
-  - [CPU/GPU (Encryption) deployment](https://paddlex.readthedocs.io/zh_CN/develop_en/deploy/server/index.html)
-  - [Deployment with OpenVINO toolkit](https://paddlex.readthedocs.io/zh_CN/develop_en/deploy/openvino/index.html)
-  - [Deploy on Nvidia Jetson](https://paddlex.readthedocs.io/zh_CN/develop_en/deploy/nvidia-jetson.html)
-  - [Deploy on Raspberry Pi](https://paddlex.readthedocs.io/zh_CN/develop_en/deploy/raspberry/index.html)
+- [PaddleX快速上手CV模型训练](https://aistudio.baidu.com/aistudio/projectdetail/450925)
+- [PaddleX快速上手——MobileNetV3-ssld 化妆品分类](https://aistudio.baidu.com/aistudio/projectdetail/450220)
+- [PaddleX快速上手——Faster-RCNN AI识虫](https://aistudio.baidu.com/aistudio/projectdetail/439888)
+- [PaddleX快速上手——DeepLabv3+ 视盘分割](https://aistudio.baidu.com/aistudio/projectdetail/440197)
 
+## 全流程产业应用案例:star:
 
+(continue to be updated)
+
+* 工业巡检:
+  * [工业表计读数](https://paddlex.readthedocs.io/zh_CN/develop/examples/meter_reader.html)
+* 工业质检:
+  - [铝材表面缺陷检测](https://paddlex.readthedocs.io/zh_CN/develop/examples/industrial_quality_inspection/README.html)
+  - [钢筋计数(动态图)](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/examples/rebar_count)
+  - [镜头缺陷检测(动态图)](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/examples/defect_detection)
+  - [机械手抓取(动态图)](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/examples/robot_grab)
+* 卫星遥感:
+  * [RGB遥感影像分割](https://paddlex.readthedocs.io/zh_CN/develop/examples/remote_sensing.html)
+  * [多通道遥感影像分割](https://paddlex.readthedocs.io/zh_CN/develop/examples/multi-channel_remote_sensing/README.html)
+  * [地块变化检测](https://paddlex.readthedocs.io/zh_CN/develop/examples/multi-channel_remote_sensing/README.html)
+* [人像分割](https://paddlex.readthedocs.io/zh_CN/develop/examples/human_segmentation.html)
+* 模型多端安全部署
+  * [CPU/GPU(加密)部署](https://paddlex.readthedocs.io/zh_CN/develop/deploy/server/index.html)
+  * [OpenVINO加速部署](https://paddlex.readthedocs.io/zh_CN/develop/deploy/openvino/index.html)
+  * [Nvidia Jetson开发板部署](https://paddlex.readthedocs.io/zh_CN/develop/deploy/jetson/index.html)
+  * [树莓派部署](https://paddlex.readthedocs.io/zh_CN/develop/deploy/raspberry/index.html)
+
+* [模型可解释性](https://paddlex.readthedocs.io/zh_CN/develop/appendix/interpret.html)
 
 ## :question:[FAQ](./docs/gui/faq.md):question:
 
+## 交流与反馈
 
+- 项目官网:https://www.paddlepaddle.org.cn/paddle/paddlex
 
-## Communication and Feedback
+- PaddleX用户交流群:957286141 (手机QQ扫描如下二维码快速加入)  
 
-- Project official website: https://www.paddlepaddle.org.cn/paddle/paddlex
-- PaddleX user group: 957286141 (Scan the following QR code on Mobile QQ to join quickly)
+  <p align="center">
+    <img src="./docs/gui/images/QR2.jpg" width="250" height ="360" alt="QR" align="middle" />
+  </p>
 
-<p align="center">
-  <img src="./docs/gui/images/QR2.jpg" width="250" height ="360" alt="QR" align="middle" />
-</p>
 
-## Release Note
 
-> [Complete Release Note](https://paddlex.readthedocs.io/zh_CN/develop/change_log.html)
-- 2020.12.20 v1.3.0
-- 2020.09.05 v1.2.0
-- 2020.07.13 v1.1.0
-- 2020.07.12 v1.0.8
-- 2020.05.20 v1.0.0
+## 更新日志
+
+> [历史版本及更新内容](https://paddlex.readthedocs.io/zh_CN/develop/change_log.html)
+- **2020.09.07 v1.2.0**
+
+  新增产业最实用目标检测模型PP-YOLO,FasterRCNN、MaskRCNN、YOLOv3、DeepLabv3p等模型新增内置COCO数据集预训练模型,适用于小模型精调。新增多种Backbone,优化体积及预测速度。优化OpenVINO、PaddleLite Android、服务端C++预测部署方案,新增树莓派部署方案等。
+
+- **2020.07.12 v1.1.0**
+
+  新增人像分割、工业标记读数案例。模型新增HRNet、FastSCNN、FasterRCNN,实例分割MaskRCNN新增Backbone HRNet。集成X2Paddle,PaddleX所有分类模型和语义分割模型支持导出为ONNX协议。新增模型加密Windows平台支持。新增Jetson、Paddle Lite模型部署预测方案。
+
+- **2020.05.20 v1.0.0**
+
+  新增C++和Python部署,模型加密部署,分类模型OpenVINO部署。新增模型可解释性接口
+
+- **2020.05.17 v0.1.8**
+
+  新增EasyData平台数据标注格式,支持imgaug数据增强库的pixel-level算子
+
+## 近期活动更新
+
+- 2020.12.16
+
+  《直击深度学习部署最后一公里 C#软件部署实战》b站直播中奖用户名单请点击[PaddleX直播中奖名单](./docs/luckydraw.md)查看~
+
+- 2020.12.09
+
+  往期直播《直击深度学习部署最后一公里 目标检测兴趣小组》回放链接:https://www.bilibili.com/video/BV1rp4y1q7ap?from=search&seid=105037779997274685
 
+## :hugs: 贡献代码:hugs:
 
+我们非常欢迎您为PaddleX贡献代码或者提供使用建议。如果您可以修复某个issue或者增加一个新功能,欢迎给我们提交Pull Requests。
 
-## :hugs: Contribution :hugs:
+### 开发者贡献项目
 
-You are welcomed to contribute codes to PaddleX or provide suggestions. If you can fix an issue or add a new feature, please feel free to submit Pull Requests.
+* [工业相机实时目标检测GUI](https://github.com/xmy0916/SoftwareofIndustrialCameraUsePaddle)
+(windows系统,基于pyqt5开发)
+* [工业相机实时目标检测GUI](https://github.com/LiKangyuLKY/PaddleXCsharp)
+(windows系统,基于C#开发)

+ 0 - 171
README_cn.md

@@ -1,171 +0,0 @@
-简体中文| [English](./README.md)
-
-
-
-
-<p align="center">
-  <img src="./docs/gui/images/paddlex.png" width="360" height ="55" alt="PaddleX" align="middle" />
-</p>
- <p align= "center"> PaddleX -- 飞桨全流程开发工具,以低代码的形式支持开发者快速实现产业实际项目落地 </p>
-
-[![License](https://img.shields.io/badge/license-Apache%202-red.svg)](LICENSE) [![Version](https://img.shields.io/github/release/PaddlePaddle/PaddleX.svg)](https://github.com/PaddlePaddle/PaddleX/releases) ![python version](https://img.shields.io/badge/python-3.6+-orange.svg) ![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全面升级动态图,目前默认使用静态图版本,动态图版本位于[dygraph](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph)中。pip安装1.3.10版本对应使用静态图版本,pip安装2.0.0rc0即使用动态图版本。
-
-:hugs: PaddleX 集成飞桨智能视觉领域**图像分类**、**目标检测**、**语义分割**、**实例分割**任务能力,将深度学习开发全流程从**数据准备**、**模型训练与优化**到**多端部署**端到端打通,并提供**统一任务API接口**及**图形化开发界面Demo**。开发者无需分别安装不同套件,以**低代码**的形式即可快速完成飞桨全流程开发。
-
-:factory: **PaddleX** 经过**质检**、**安防**、**巡检**、**遥感**、**零售**、**医疗**等十多个行业实际应用场景验证,沉淀产业实际经验,**并提供丰富的案例实践教程**,全程助力开发者产业实践落地。
-
-
-
-:heart:**您可以前往  [完整PaddleX在线使用文档目录](https://paddlex.readthedocs.io/zh_CN/develop/index.html)  查看完整*Read the Doc* 格式的文档,获得更好的阅读体验**:heart:
-
-
-
-![](./docs/gui/images/paddlexoverview.png)
-
-
-
-## 安装
-
-**PaddleX提供三种开发模式,满足用户的不同需求:**
-
-1. **Python开发模式:**
-
-   通过简洁易懂的Python API,在兼顾功能全面性、开发灵活性、集成方便性的基础上,给开发者最流畅的深度学习开发体验。<br>
-
-  **前置依赖**
-> - paddlepaddle >= 1.8.4
-> - python >= 3.6
-> - cython
-> - pycocotools
-
-```
-pip install paddlex -i https://mirror.baidu.com/pypi/simple
-```
-详细安装方法请参考[PaddleX安装](https://paddlex.readthedocs.io/zh_CN/develop/install.html)
-
-
-2. **Padlde GUI模式:**
-
-   无代码开发的可视化客户端,应用Paddle API实现,使开发者快速进行产业项目验证,并为用户开发自有深度学习软件/应用提供参照。
-
-- 前往[PaddleX官网](https://www.paddlepaddle.org.cn/paddle/paddlex),申请下载PaddleX GUI一键绿色安装包。
-
-- 前往[PaddleX GUI使用教程](./docs/gui/how_to_use.md)了解PaddleX GUI使用详情。
-
-- [PaddleX GUI安装环境说明](./docs/gui/download.md)
-
-3. **PaddleX Restful:**  
-  使用基于RESTful API开发的GUI与Web Demo实现远程的深度学习全流程开发;同时开发者也可以基于RESTful API开发个性化的可视化界面
-- 前往[PaddleX RESTful API使用教程](./docs/gui/restful/introduction.md)  
-
-
-## 产品模块说明
-
-- **数据准备**:兼容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说明
-
-- [完整PaddleX在线使用文档目录](https://paddlex.readthedocs.io/zh_CN/develop/index.html):heart:
-
-- [10分钟快速上手系列教程](https://paddlex.readthedocs.io/zh_CN/develop/quick_start.html)
-- [PaddleX模型训练教程集合](https://paddlex.readthedocs.io/zh_CN/develop/train/index.html)
-- [PaddleX API接口说明](https://paddlex.readthedocs.io/zh_CN/develop/apis/index.html)
-- [PaddleX RESTful API说明](https://paddlex.readthedocs.io/zh_CN/develop/gui/restful/introduction.html)
-
-### 在线项目示例
-
-为了使开发者更快掌握PaddleX API,我们创建了一系列完整的示例教程,您可通过AIStudio一站式开发平台,快速在线运行PaddleX的项目。
-
-- [PaddleX快速上手CV模型训练](https://aistudio.baidu.com/aistudio/projectdetail/450925)
-- [PaddleX快速上手——MobileNetV3-ssld 化妆品分类](https://aistudio.baidu.com/aistudio/projectdetail/450220)
-- [PaddleX快速上手——Faster-RCNN AI识虫](https://aistudio.baidu.com/aistudio/projectdetail/439888)
-- [PaddleX快速上手——DeepLabv3+ 视盘分割](https://aistudio.baidu.com/aistudio/projectdetail/440197)
-
-## 全流程产业应用案例:star:
-
-(continue to be updated)
-
-* 工业巡检:
-  * [工业表计读数](https://paddlex.readthedocs.io/zh_CN/develop/examples/meter_reader.html)
-* 工业质检:
-  * [铝材表面缺陷检测](https://paddlex.readthedocs.io/zh_CN/develop/examples/industrial_quality_inspection/README.html)
-* 卫星遥感:
-  * [RGB遥感影像分割](https://paddlex.readthedocs.io/zh_CN/develop/examples/remote_sensing.html)
-  * [多通道遥感影像分割](https://paddlex.readthedocs.io/zh_CN/develop/examples/multi-channel_remote_sensing/README.html)
-  * [地块变化检测](https://paddlex.readthedocs.io/zh_CN/develop/examples/multi-channel_remote_sensing/README.html)
-* [人像分割](https://paddlex.readthedocs.io/zh_CN/develop/examples/human_segmentation.html)
-* 模型多端安全部署
-  * [CPU/GPU(加密)部署](https://paddlex.readthedocs.io/zh_CN/develop/deploy/server/index.html)
-  * [OpenVINO加速部署](https://paddlex.readthedocs.io/zh_CN/develop/deploy/openvino/index.html)
-  * [Nvidia Jetson开发板部署](https://paddlex.readthedocs.io/zh_CN/develop/deploy/jetson/index.html)
-  * [树莓派部署](https://paddlex.readthedocs.io/zh_CN/develop/deploy/raspberry/index.html)
-
-* [模型可解释性](https://paddlex.readthedocs.io/zh_CN/develop/appendix/interpret.html)
-
-## :question:[FAQ](./docs/gui/faq.md):question:
-
-## 交流与反馈
-
-- 项目官网:https://www.paddlepaddle.org.cn/paddle/paddlex
-
-- PaddleX用户交流群:957286141 (手机QQ扫描如下二维码快速加入)  
-
-  <p align="center">
-    <img src="./docs/gui/images/QR2.jpg" width="250" height ="360" alt="QR" align="middle" />
-  </p>
-
-
-
-## 更新日志
-
-> [历史版本及更新内容](https://paddlex.readthedocs.io/zh_CN/develop/change_log.html)
-- **2020.09.07 v1.2.0**
-
-  新增产业最实用目标检测模型PP-YOLO,FasterRCNN、MaskRCNN、YOLOv3、DeepLabv3p等模型新增内置COCO数据集预训练模型,适用于小模型精调。新增多种Backbone,优化体积及预测速度。优化OpenVINO、PaddleLite Android、服务端C++预测部署方案,新增树莓派部署方案等。
-
-- **2020.07.12 v1.1.0**
-
-  新增人像分割、工业标记读数案例。模型新增HRNet、FastSCNN、FasterRCNN,实例分割MaskRCNN新增Backbone HRNet。集成X2Paddle,PaddleX所有分类模型和语义分割模型支持导出为ONNX协议。新增模型加密Windows平台支持。新增Jetson、Paddle Lite模型部署预测方案。
-
-- **2020.05.20 v1.0.0**
-
-  新增C++和Python部署,模型加密部署,分类模型OpenVINO部署。新增模型可解释性接口
-
-- **2020.05.17 v0.1.8**
-
-  新增EasyData平台数据标注格式,支持imgaug数据增强库的pixel-level算子
-
-## 近期活动更新
-
-- 2020.12.16
-
-  《直击深度学习部署最后一公里 C#软件部署实战》b站直播中奖用户名单请点击[PaddleX直播中奖名单](./docs/luckydraw.md)查看~
-
-- 2020.12.09
-
-  往期直播《直击深度学习部署最后一公里 目标检测兴趣小组》回放链接:https://www.bilibili.com/video/BV1rp4y1q7ap?from=search&seid=105037779997274685
-
-## :hugs: 贡献代码:hugs:
-
-我们非常欢迎您为PaddleX贡献代码或者提供使用建议。如果您可以修复某个issue或者增加一个新功能,欢迎给我们提交Pull Requests。
-
-### 开发者贡献项目
-
-* [工业相机实时目标检测GUI](https://github.com/xmy0916/SoftwareofIndustrialCameraUsePaddle)
-(windows系统,基于pyqt5开发)
-* [工业相机实时目标检测GUI](https://github.com/LiKangyuLKY/PaddleXCsharp)
-(windows系统,基于C#开发)

+ 145 - 0
README_en.md

@@ -0,0 +1,145 @@
+[简体中文](./README_cn.md) | English
+
+
+
+
+
+<p align="center">
+  <img src="./docs/gui/images/paddlex.png" width="360" height ="55" alt="PaddleX" align="middle" />
+</p>
+
+
+<p align= "center"> PaddleX -- PaddlePaddle End-to-End Development Toolkit,
+  enables developers to implement real industry projects in a low-code form quickly </p>
+
+[![License](https://img.shields.io/badge/license-Apache%202-red.svg)](LICENSE) [![Version](https://img.shields.io/github/release/PaddlePaddle/PaddleX.svg)](https://github.com/PaddlePaddle/PaddleX/releases) ![python version](https://img.shields.io/badge/python-3.6+-orange.svg) ![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 dynamic graph mode is ready! Static graph mode is set as default and dynamic graph code base is in [dygraph](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph). If you want to use static graph mode, the version 1.3.11 can be installed by pip. The version 2.0.0rc0 corresponds to the dynamic graph mode.
+
+
+:hugs:  PaddleX integrated the abilities of **Image classification**, **Object detection**, **Semantic segmentation**, and **Instance segmentation** in the Paddle CV toolkits, and get through the whole-process development from **Data preparation** and **Model training and optimization** to **Multi-end deployment**. At the same time, PaddleX provides **Succinct APIs** and a **Graphical User Interface**. Developers can quickly complete the end-to-end process development of the Paddle in a form of **low-code**  without installing different libraries.
+
+**:factory: PaddleX** has been validated in a dozen of industry application scenarios such as **Quality Inspection**, **Security**, **Patrol Inspection**, **Remote Sensing**, **Retail**,  **Medical** etc.. In addition, it **provides a wealth of case practice tutorials**, to help developer could apply to actual cases easily.
+
+
+
+:heart: **You can go to [Complete PaddleX Online Documentation Contents](https://paddlex.readthedocs.io/zh_CN/develop_en/index.html) for complete tutorial with the format of *Read the Doc* and better reading experience​** :heart:
+
+
+
+![](./docs/gui/images/paddlexoverview_en.jpg)
+
+
+
+## Installation
+
+**PaddleX has two development modes to meet different needs of users:**
+
+1.**Python development mode:**
+
+The design of PaddleX Python API taking into account of comprehensive functions, development flexibility, and integration convenience, giving developers the smoothest deep learning development experience.
+
+**Pre-dependence**
+
+> - paddlepaddle >= 1.8.4
+> - python >= 3.6
+> - cython
+> - pycocotools
+
+You shuould use command of python3 and pip3 instead if you have python2 installed.
+
+```
+pip install paddlex -i https://mirror.baidu.com/pypi/simple
+```
+Please refer to the [PaddleX installation](https://paddlex.readthedocs.io/zh_CN/develop/install.html) for detailed installation method.
+
+
+2. **Padlde GUI(Graphical User Interface) mode:**
+
+It's a all-in-one client enable develops could implement deep learning projects without code.
+
+- Go to [PaddleX Official Website](https://www.paddlepaddle.org.cn/paddle/paddlex) to download the all-in-one client.
+
+- Go to [PaddleX GUI tutorial](./docs/gui/how_to_use.md ) for details of using it.
+
+- [PaddleX GUI Environment Requirements for Installation](./docs/gui/download.md)
+
+
+## Product Module Description
+
+- **Data preparation**: Compatible with common data protocols such as ImageNet, VOC, COCO, and seamlessly interconnecting with Labelme, Colabeler, and [EasyData intelligent data service platform](https://ai.baidu.com/easydata/), to help developers to quickly complete data preparations.
+- **Data pre-processing and enhancement**: Provides a minimalist image pre-processing and enhancement method--Transforms. Adapts imgaug which is a powerful image enhancement library, so that PaddleX could supports **Hundreds of data enhancement strategies**, which makes developers quickly alleviate the situation of traing with small sample dataset.
+- **Model training**: PaddleX integrates [PaddleClas](https://github.com/PaddlePaddle/PaddleClas), [PaddleDetection](https://github.com/PaddlePaddle/PaddleDetection), and [PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg) etcs. So it provides a large number of selected, industry-proven, high-quality pre-trained models, enabling developers to achieve the industry requirements much more quickly.
+- **Model tuning**: Model-interpretability module and [VisualDL](https://github.com/PaddlePaddle/VisualDL) visual analysis tool are integrated as well. It allows developers to understand the model's feature extraction region and the change of the training process parameters more intuitively , so as to quickly optimize the model.
+- **Multi-End Secure Deployment**: The built-in model compression tool-- [PaddleSlim](https://github.com/PaddlePaddle/PaddleSlim)  and **Model Encryption Deployment Module**, are seamlessly interconnected with native prediction library **Paddle Inference** and Multi-platform high performance deep learning inference engine-- [Paddle Lite](https://github.com/PaddlePaddle/Paddle-Lite) , to enable developers to quickly implement multi-end, high-performance, secure deployments of the model.
+
+
+
+## Full Documentation and API Description
+
+- [Complete PaddleX online documentation contents](https://paddlex.readthedocs.io/zh_CN/develop_en/):heart:
+
+- [10-Minute Quick Start Tutorial Series](https://paddlex.readthedocs.io/zh_CN/develop/quick_start.html)
+- [Collection of PaddleX Model Training Tutorials](https://paddlex.readthedocs.io/zh_CN/develop/train/index.html)
+- [PaddleX API Interface Description](https://paddlex.readthedocs.io/zh_CN/develop/apis/index.html)
+
+### Examples of Online Projects
+
+To get developers up to speed with the PaddleX API, we've created a complete series of sample tutorials that you can run PaddleX projects online through the **AIStudio** quickly.
+
+- [PaddleX Quick Start - CV Model Training](https://aistudio.baidu.com/aistudio/projectdetail/450925)
+- [PaddleX Quick Start - MobileNetV3-ssld Cosmetics Classification](https://aistudio.baidu.com/aistudio/projectdetail/450220)
+- [PaddleX Quick Start - Faster-RCNN AI Bug Recognition](https://aistudio.baidu.com/aistudio/projectdetail/439888)
+- [PaddleX Quick Start - DeepLabv3+ Semantic Segmentation](https://aistudio.baidu.com/aistudio/projectdetail/440197)
+
+
+
+## Full Process Industry Applications:star:
+
+(continue to be updated)
+
+* Industrial inspections:
+  - [Industrial Meter Readings](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/meter_reader.html)
+* [Industrial quality control](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/industrial_quality_inspection/README.html)
+* Satellite Image Understanding:
+  * [RGB Satellite Image Segmentation](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/remote_sensing.html)
+  * [Multi-Channel Satellite Image Segmentation](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/multi-channel_remote_sensing/README.html)
+  * [Land Parcel Change Detection](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/change_detection.html)
+* [Portrait Segmentation](https://paddlex.readthedocs.io/zh_CN/develop_en/examples/human_segmentation.html)
+* Multi-platform Deployment with Encryption
+  - [CPU/GPU (Encryption) deployment](https://paddlex.readthedocs.io/zh_CN/develop_en/deploy/server/index.html)
+  - [Deployment with OpenVINO toolkit](https://paddlex.readthedocs.io/zh_CN/develop_en/deploy/openvino/index.html)
+  - [Deploy on Nvidia Jetson](https://paddlex.readthedocs.io/zh_CN/develop_en/deploy/nvidia-jetson.html)
+  - [Deploy on Raspberry Pi](https://paddlex.readthedocs.io/zh_CN/develop_en/deploy/raspberry/index.html)
+
+
+
+## :question:[FAQ](./docs/gui/faq.md):question:
+
+
+
+## Communication and Feedback
+
+- Project official website: https://www.paddlepaddle.org.cn/paddle/paddlex
+- PaddleX user group: 957286141 (Scan the following QR code on Mobile QQ to join quickly)
+
+<p align="center">
+  <img src="./docs/gui/images/QR2.jpg" width="250" height ="360" alt="QR" align="middle" />
+</p>
+
+## Release Note
+
+> [Complete Release Note](https://paddlex.readthedocs.io/zh_CN/develop/change_log.html)
+- 2020.12.20 v1.3.0
+- 2020.09.05 v1.2.0
+- 2020.07.13 v1.1.0
+- 2020.07.12 v1.0.8
+- 2020.05.20 v1.0.0
+
+
+
+## :hugs: Contribution :hugs:
+
+You are welcomed to contribute codes to PaddleX or provide suggestions. If you can fix an issue or add a new feature, please feel free to submit Pull Requests.

+ 144 - 0
docs/Resful_API/docs/readme.md

@@ -0,0 +1,144 @@
+# PaddleX_Restful API --快速搭建私有化训练云服务
+
+* ## 什么是Resetful
+* ## PaddleX_Restful API 说明
+* ## 如何快速使用PaddleX_Restful API 快速搭建私有化训练云平台
+
+
+
+## *什么是Resetful*
+
+RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。
+
+简单来说就是用户可以起一个远端的服务,客户端通过http形式进行访问。
+
+## *PaddleX_Restful API 说明*
+
+PaddleX RESTful是基于PaddleX开发的RESTful API。对于开发者来说只需要简单的指令便可开启PaddleX RESTful服务。对于哪些有远程训练要求,同时为了数据保密的开发者来说,PaddleX_Restful API简单易用的操作可以很好的满足上述要求。
+
+开启RESTful服务后可以实现如下功能:
+
+* 通过下载基于RESTful API的GUI连接开启RESTful服务的服务端,实现远程深度学习全流程开发。
+* 通过使用web demo连接开启RESTful服务的服务端,实现远程深度学习全流程开发。
+* 根据RESTful API来开发您自己个性化的可视化界面。
+
+
+<div align="center">
+<img src="../images/1.png"  width = "500" />              </div>
+
+## *如何快速使用PaddleX_Restful API 快速搭建私有化训练云平台*
+
+在该示例中PaddleX_Restful运行在一台带GPU的linux服务器下,用户通过其他电脑连接该服务器进行远程的操作。
+### 1  环境准备
+在服务器下载PaddlePaddle和PaddleX及其他依赖
+
+* 下载PaddlePaddle
+
+`pip install paddlepaddle-gpu -i `
+
+* 下载PaddleX
+
+pip install paddlex==1.3.11 -i
+
+* 下载pycuda(如果不使用GPU,该项可不进行下载)
+
+pip install pycuda -i
+
+### 2  启动Restful服务
+
+在服务器上启动如下命令,其中端口号是用户自定义的,`workspace_dir`是用户在服务器创建的
+
+`paddlex_restful --start_restful --port [端口号] --workspace_dir [工作空间地址]`
+
+例如开启一个端口为27000,工作路径在`cv/x/resful_space`的一个服务
+
+`paddlex_restful --start_restful --port 27000 --workspace_dir cv/x/resful_space`
+
+<div align="center">
+<img src="../images/2.png"  width = "800" />              </div>
+
+出现上述图片所示的内容,即为开启服务成功。
+
+### 3 启动客户端进行远程全流程训练
+
+为了方便大家进行远程调试,PaddleX_Restful提供了两张访问形式,一个是Web图形化界面,另一个是客户端的图形化界面
+* ## Web图像化界面
+
+### 3.1 打开Web界面
+当用户启动Restful服务后,在Web界面的导航栏只需要输入IP地址和端口号即可。例如当前案例的IP地址是222.95.100.37 端口号是25001
+
+即在导航栏输入 `http://222.95.100.37:25001/` 即可出现如下界面
+
+<div align="center">
+<img src="../images/2.5.png"  width = "800" />              </div>
+
+### 3.2 服务器设置
+点击界面中内容,在将服务器进行设置
+
+<div align="center">
+<img src="../images/2.6.png"  width = "800" />              </div>
+
+### 3.3 下载示例项目
+
+用户根据自己的需求,选择是否下载示例项目
+
+<div align="center">
+<img src="../images/3.png"  width = "800" />              </div>
+
+最终画面如下图所示
+
+<div align="center">
+<img src="../images/4.png"  width = "800" />              </div>
+
+### 3.4 创建数据集
+用户如果要自定义训练,首先需要去创建用户自身的数据集,
+在此之前,用户首先需要将数据集上传到服务器上。
+
+<div align="center">
+<img src="../images/5.png"  width = "800" />              </div>
+
+输入在服务上数据存储的路径,开始导入数据,在服务器上传的数据集,必须是符合PaddleX训练数据的命名格式要求。
+
+<div align="center">
+<img src="../images/5.5.png"  width = "800" />              </div>
+
+<div align="center">
+<img src="../images/6.png"  width = "800" />              </div>
+
+数据导入成功后,进行数据集划分
+<div align="center">
+<img src="../images/7.png"  width = "800" />              </div>
+
+用户在划分完成数据集后,也可对数据集进行可视化观察
+<div align="center">
+<img src="../images/8.png"  width = "800" />              </div>
+
+### 3.5 开始训练
+
+在数据集创建完成后,用户可创建新项目,并进行训练
+
+<div align="center">
+<img src="../images/9.png"  width = "800" />              </div>
+
+配置好相关参数后,点击开始训练,便开始进行训练。
+<div align="center">
+<img src="../images/10.png"  width = "800" />              </div>
+
+
+* ## 客户端图形化界面
+客户端操作流程和Web界面基本一致,提供了MAC和Windows版本两种,用户可自行下载并操作
+
+- [MAC](https://bj.bcebos.com/paddlex/PaddleX_Remote_GUI/mac/PaddleX_Remote_GUI.zip)
+- [Windows](https://bj.bcebos.com/paddlex/PaddleX_Remote_GUI/windows/PaddleX_Remote_GUI.zip)
+
+### 4  Restful 二次开发说明
+
+开发者可以使用PaddleX RESTful API 进行二次开发,按照自己的需求开发可视化界面,详细请参考以下文档  
+
+[RESTful API 二次开发简介](https://github.com/PaddlePaddle/PaddleX/blob/develop/docs/gui/restful/restful.md)  
+
+[快速开始](https://github.com/PaddlePaddle/PaddleX/blob/develop/docs/gui/restful/quick_start.md)  
+
+[API 参考文档](https://github.com/PaddlePaddle/PaddleX/blob/develop/docs/gui/restful/restful_api.md)  
+
+[自定义数据结构](https://github.com/PaddlePaddle/PaddleX/blob/develop/docs/gui/restful/data_struct.md)

二进制
docs/Resful_API/images/1.png


二进制
docs/Resful_API/images/10.png


二进制
docs/Resful_API/images/2.5.png


二进制
docs/Resful_API/images/2.6.png


二进制
docs/Resful_API/images/2.png


二进制
docs/Resful_API/images/3.png


二进制
docs/Resful_API/images/4.png


二进制
docs/Resful_API/images/5.5.png


二进制
docs/Resful_API/images/5.png


二进制
docs/Resful_API/images/6.png


二进制
docs/Resful_API/images/7.png


二进制
docs/Resful_API/images/8.png


二进制
docs/Resful_API/images/9.png


+ 46 - 10
dygraph/README.md

@@ -7,6 +7,13 @@
 </p>
  <p align= "center"> PaddleX -- 飞桨全流程开发工具,以低代码的形式支持开发者快速实现产业实际项目落地 </p>
 
+## :heart:重磅功能升级
+* 全新发布Manufacture SDK,提供工业级多端多平台部署加速的预编译飞桨部署开发包(SDK),通过配置业务逻辑流程文件即可以低代码方式快速完成推理部署[欢迎体验](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/deploy/cpp)。
+
+* PaddleX部署全面升级,支持飞桨视觉套件PaddleDetection、PaddleClas、PaddleSeg、PaddleX的统一部署能力。[欢迎体验](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/deploy/cpp)。
+
+
+
 [![License](https://img.shields.io/badge/license-Apache%202-red.svg)](LICENSE) [![Version](https://img.shields.io/github/release/PaddlePaddle/PaddleX.svg)](https://github.com/PaddlePaddle/PaddleX/releases) ![python version](https://img.shields.io/badge/python-3.6+-orange.svg) ![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)
 
@@ -34,13 +41,21 @@
 
   **前置依赖**
 > - paddlepaddle == 2.1.0
-> - python >= 3.6
-> - cython
-> - pycocotools
+> - 安装PaddlePaddle Develop版本,具体PaddlePaddle[安装主页](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/develop/install/pip/windows-pip.html)
+
+**安装方式**
+
+> - git clone --recurse-submodules https://github.com/PaddlePaddle/PaddleX.git
+> - cd PaddleX/dygraph
+> - pip install -r requirements.txt
+> - pip install -r submodules.txt
+> - python setup.py install
+
 
-```
-pip install paddlex==2.0.0rc -i https://mirror.baidu.com/pypi/simple
-```
+**特别说明**   Windows除了执行上述命令外,还需要下载pycocotools
+
+> - pip install cython
+> - pip install git+https://gitee.com/jiangjiajun/philferriere-cocoapi.git#subdirectory=PythonAPI
 
 
 2. **Padlde GUI模式:**
@@ -55,16 +70,37 @@ pip install paddlex==2.0.0rc -i https://mirror.baidu.com/pypi/simple
 
 3. **PaddleX Restful:**  
   使用基于RESTful API开发的GUI与Web Demo实现远程的深度学习全流程开发;同时开发者也可以基于RESTful API开发个性化的可视化界面
-- 前往[PaddleX RESTful API使用教程](../docs/gui/restful/introduction.md)  
+- 前往[PaddleX RESTful API使用教程](../docs/Resful_API/docs/readme.md)  
 
 
 ## 使用教程
 
-- [模型训练教程](https://github.com/PaddlePaddle/PaddleX/tree/release/2.0-rc/tutorials/train)
-- [模型剪裁教程](https://github.com/PaddlePaddle/PaddleX/tree/release/2.0-rc/tutorials/slim/prune)
+1. **API模式:**
+
+- [模型训练](https://github.com/PaddlePaddle/PaddleX/tree/release/2.0-rc/tutorials/train)
+- [模型剪裁](https://github.com/PaddlePaddle/PaddleX/tree/release/2.0-rc/tutorials/slim/prune)
+
+
+
+2. **GUI模式:**
+
+- [图像分类](https://www.bilibili.com/video/BV1nK411F7J9?from=search&seid=3068181839691103009)
+- [目标检测](https://www.bilibili.com/video/BV1HB4y1A73b?from=search&seid=3068181839691103009)
+- [实例分割](https://www.bilibili.com/video/BV1M44y1r7s6?from=search&seid=3068181839691103009)
+- [语义分割](https://www.bilibili.com/video/BV1qQ4y1Z7co?from=search&seid=3068181839691103009)
 
+3. **模型部署:**
+- [Manufacture SDK](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/deploy/cpp)
+提供工业级多端多平台部署加速的预编译飞桨部署开发包(SDK),通过配置业务逻辑流程文件即可以低代码方式快速完成推理部署
+- [PaddleX Deploy](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/deploy/cpp) 支持飞桨视觉套件PaddleDetection、PaddleClas、PaddleSeg、PaddleX的统一部署能力
+## 产业级应用示例
 
-## :question:[FAQ](../docs/gui/faq.md):question:
+- [钢筋计数](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/examples/rebar_count)
+- [缺陷检测](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/examples/defect_detection)
+- [机械手抓取](https://github.com/PaddlePaddle/PaddleX/tree/develop/dygraph/examples/robot_grab)
+- [表计检测]()
+## :question:[FAQ]
+(../docs/gui/faq.md):question:
 
 ## 交流与反馈
 

+ 7 - 1
dygraph/deploy/cpp/model_deploy/common/include/transforms.h

@@ -68,8 +68,8 @@ class Normalize : public Transform {
       if (is_scale_) {
         alpha /= (max_val_[c] - min_val_[c]);
       }
+      double beta = -1.0 * (mean_[c] + min_val_[c] * alpha) / std_[c];
       alpha /= std_[c];
-      double beta = -1.0 * mean_[c] / std_[c];
 
       alpha_.push_back(alpha);
       beta_.push_back(beta);
@@ -166,6 +166,11 @@ class Resize : public Transform {
     } else {
       use_scale_ = true;
     }
+    if (item["keep_ratio"].IsDefined()) {
+      keep_ratio_ = item["keep_ratio"].as<bool>();
+    } else {
+      keep_ratio_ = false;
+    }
     height_ = item["height"].as<int>();
     width_ = item["width"].as<int>();
     if (height_ <= 0 || width_ <= 0) {
@@ -184,6 +189,7 @@ class Resize : public Transform {
   int width_;
   int interp_;
   bool use_scale_;
+  bool keep_ratio_;
 };
 
 class BGR2RGB : public Transform {

+ 22 - 4
dygraph/deploy/cpp/model_deploy/common/src/transforms.cpp

@@ -147,9 +147,15 @@ bool Resize::Run(cv::Mat *im) {
               << std::endl;
     return false;
   }
+  double scale_w = width_ / static_cast<double>(im->cols);
+  double scale_h = height_ / static_cast<double>(im->rows);
+  if (keep_ratio_) {
+    scale_h = std::min(scale_w, scale_h);
+    scale_w = scale_h;
+    width_ = static_cast<int>(round(scale_w * im->cols));
+    height_ = static_cast<int>(round(scale_h * im->rows));
+  }
   if (use_scale_) {
-    double scale_w = width_ / static_cast<double>(im->cols);
-    double scale_h = height_ / static_cast<double>(im->rows);
     cv::resize(*im, *im, cv::Size(), scale_w, scale_h, interp_);
   } else {
     cv::resize(*im, *im, cv::Size(width_, height_), 0, 0, interp_);
@@ -161,8 +167,20 @@ bool Resize::ShapeInfer(
         const std::vector<int>& in_shape,
         std::vector<int>* out_shape) {
   out_shape->clear();
-  out_shape->push_back(width_);
-  out_shape->push_back(height_);
+  double width = width_;
+  double height = height_;
+  if (keep_ratio_) {
+    int w = in_shape[0];
+    int h = in_shape[1];
+    double scale_w = width_ / static_cast<double>(w);
+    double scale_h = height_ / static_cast<double>(h);
+    scale_h = std::min(scale_w, scale_h);
+    scale_w = scale_h;
+    width = static_cast<int>(round(scale_w * w));
+    height = static_cast<int>(round(scale_h * h));
+  }
+  out_shape->push_back(width);
+  out_shape->push_back(height);
   return true;
 }
 

+ 51 - 2
dygraph/deploy/cpp/model_deploy/paddlex/include/x_standard_config.h

@@ -51,6 +51,9 @@ void XNormalize(const YAML::Node& src, YAML::Node* dst) {
     (*dst)["transforms"]["Normalize"]["mean"].push_back(mean[i]);
     (*dst)["transforms"]["Normalize"]["std"].push_back(std[i]);
   }
+  if (src["is_scale"].IsDefined()) {
+    (*dst)["transforms"]["Normalize"]["is_scale"] = src["is_scale"];
+  }
 }
 
 void XResize(const YAML::Node& src, YAML::Node* dst) {
@@ -62,8 +65,13 @@ void XResize(const YAML::Node& src, YAML::Node* dst) {
     w = src["target_size"].as<int>();
     h = src["target_size"].as<int>();
   } else if (src["target_size"].IsSequence()) {
-    w = src["target_size"].as<std::vector<int>>()[0];
-    h = src["target_size"].as<std::vector<int>>()[1];
+    if ((*dst)["version"].as<std::string>() >= "2.0.0") {
+      h = src["target_size"].as<std::vector<int>>()[0];
+      w = src["target_size"].as<std::vector<int>>()[1];
+    } else {
+      w = src["target_size"].as<std::vector<int>>()[0];
+      h = src["target_size"].as<std::vector<int>>()[1];
+    }
   } else {
     std::cerr << "[ERROR] Unexpected value type of `target_size`" << std::endl;
     assert(false);
@@ -87,6 +95,9 @@ void XResize(const YAML::Node& src, YAML::Node* dst) {
       assert(false);
     }
   }
+  if (src["keep_ratio"].IsDefined() && src["keep_ratio"].as<bool>()) {
+    (*dst)["transforms"]["Resize"]["keep_ratio"] = true;
+  }
   (*dst)["transforms"]["Resize"]["width"] = w;
   (*dst)["transforms"]["Resize"]["height"] = h;
   (*dst)["transforms"]["Resize"]["interp"] = interp;
@@ -116,6 +127,44 @@ void XResizeByShort(const YAML::Node& src, YAML::Node* dst) {
   (*dst)["transforms"]["ResizeByShort"]["use_scale"] = false;
 }
 
+// dygraph version
+void XPaddingV2(const YAML::Node& src, YAML::Node* dst) {
+  if (src["target_size"].IsDefined() &&
+      src["target_size"].Type() != YAML::NodeType::Null) {
+    assert(src["target_size"].IsScalar() || src["target_size"].IsSequence());
+    if (src["target_size"].IsScalar()) {
+      (*dst)["transforms"]["Padding"]["width"] = src["target_size"].as<int>();
+      (*dst)["transforms"]["Padding"]["height"] = src["target_size"].as<int>();
+    } else {
+      std::vector<int> target_size = src["target_size"].as<std::vector<int>>();
+      (*dst)["transforms"]["Padding"]["width"] = target_size[0];
+      (*dst)["transforms"]["Padding"]["height"] = target_size[1];
+    }
+  } else if (src["size_divisor"].IsDefined()) {
+    (*dst)["transforms"]["Padding"]["stride"] =
+                        src["size_divisor"].as<int>();
+  } else {
+    std::cerr << "[Error] As least one of size_divisor/"
+              << "target_size must be defined for Padding"
+              << std::endl;
+    assert(false);
+  }
+
+  if (src["im_padding_value"].IsDefined()) {
+    (*dst)["transforms"]["Padding"]["im_padding_value"] =
+            src["im_padding_value"].as<std::vector<float>>();
+  }
+
+  if (src["pad_mode"].IsDefined()) {
+    if (src["pad_mode"].as<int>() != 0) {
+      std::cerr << "[Error] No support pad_mode :"
+              << src["pad_mode"].as<int>()
+              << std::endl;
+      assert(false);
+    }
+  }
+}
+
 void XPadding(const YAML::Node& src, YAML::Node* dst) {
   if (src["coarsest_stride"].IsDefined()) {
     (*dst)["transforms"]["Padding"]["stride"] =

+ 5 - 1
dygraph/deploy/cpp/model_deploy/paddlex/src/x_model.cpp

@@ -32,7 +32,11 @@ bool PaddleXModel::GenerateTransformsConfig(const YAML::Node& src) {
     } else if (op_name == "ResizeByLong") {
       XResizeByLong(op.begin()->second, &yaml_config_);
     } else if (op_name == "Padding") {
-      XPadding(op.begin()->second, &yaml_config_);
+      if (src["version"].as<std::string>() >= "2.0.0") {
+        XPaddingV2(op.begin()->second, &yaml_config_);
+      } else {
+        XPadding(op.begin()->second, &yaml_config_);
+      }
     } else if (op_name == "CenterCrop") {
       XCenterCrop(op.begin()->second, &yaml_config_);
     } else if (op_name == "Resize") {

+ 3 - 1
dygraph/examples/README.md

@@ -3,6 +3,8 @@
 
 * [钢筋计数](./rebar_count)
 
-* [机械手抓取](./robat_grab)
+* [机械手抓取](./robot_grab)
 
 * [缺陷检测](./defect_detection)
+
+* [工业表计检测](./meter_reader)

+ 321 - 0
dygraph/examples/meter_reader/README.md

@@ -0,0 +1,321 @@
+# 工业指针型表计读数
+
+## 目录
+
+* [1 项目说明](#1)
+* [2 数据准备](#2)
+* [3 模型选择](#3)
+* [4 表计检测模型训练](#4)
+* [5 指针和刻度分割模型训练](#5)
+* [6 模型预测](#6)
+
+## <h2 id="1">1 项目说明</h2>
+
+在该项目中,主要向大家介绍如何使用目标检测和语义分割来实现对指针型表计读数。
+
+在电力能源厂区需要定期监测表计读数,以保证设备正常运行及厂区安全。但厂区分布分散,人工巡检耗时长,无法实时监测表计,且部分工作环境危险导致人工巡检无法触达。针对上述问题,希望通过摄像头拍照->智能读数的方式高效地完成此任务。
+
+<div align="center">
+<img src="./images/scene_introduce.jpg"  width = "800" />              </div>
+
+为实现智能读数,我们采取目标检测->语义分割->读数后处理的方案:
+
+* 第一步,使用目标检测模型定位出图像中的表计;
+* 第二步,使用语义分割模型将各表计的指针和刻度分割出来;
+* 第三步,根据指针的相对位置和预知的量程计算出各表计的读数。
+
+整个方案的流程如下所示:
+
+<div align="center">
+<img src="images/MeterReader_Architecture.jpg"  width = "800" />              </div>
+
+
+## <h2 id="2">2 数据准备</h2>
+
+本案例开放了表计检测数据集、指针和刻度分割数据集、表计测试图片(只有图片无真值标注),使用这些图片可以完成目标检测模型、语义分割模型的训练、模型预测。点击下表中的链接可下载数据集,**提前下载数据集不是必须的,因为在接下来的模型训练部分中提供的训练脚本会自动下载数据集**。
+
+| 表计测试图片                                                 | 表计检测数据集                                               | 指针和刻度分割数据集                                         |
+| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
+| [meter_test](https://bj.bcebos.com/paddlex/examples/meter_reader/datasets/meter_test.tar.gz) | [meter_det](https://bj.bcebos.com/paddlex/examples/meter_reader/datasets/meter_det.tar.gz) | [meter_seg](https://bj.bcebos.com/paddlex/examples/meter_reader/datasets/meter_seg.tar.gz) |
+
+| 表计检测数据集 | 指针和刻度分割数据集 |
+| -- | -- |
+| ![](./images/det_data.png) | ![](./images/seg_data.png) |
+
+
+* 解压后的表计检测数据集的文件夹内容如下:
+
+训练集有725张图片,测试集有58张图片。
+
+```
+meter_det/
+|-- annotations/ # 标注文件所在文件夹
+|   |-- instance_train.json # 训练集标注文件
+|   |-- instance_test.json # 测试集标注文件
+|-- test/ # 测试图片所在文件夹
+|   |-- 20190822_105.jpg # 测试集图片
+|   |-- ... ...
+|-- train/ # 训练图片所在文件夹
+|   |-- 20190822_101.jpg # 训练集图片
+|   |-- ... ...
+
+```
+
+* 解压后的指针和刻度分割数据集的文件夹内容如下:
+
+训练集有374张图片,测试集有40张图片。
+
+```
+meter_seg/
+|-- annotations/ # 标注文件所在文件夹
+|   |-- train # 训练集标注图片所在文件夹
+|   |   |-- 105.png
+|   |   |-- ... ...
+|   |-- val # 验证集合标注图片所在文件夹
+|   |   |-- 110.png
+|   |   |-- ... ...
+|-- images/ # 图片所在文件夹
+|   |-- train # 训练集图片
+|   |   |-- 105.jpg
+|   |   |-- ... ...
+|   |-- val # 验证集图片
+|   |   |-- 110.jpg
+|   |   |-- ... ...
+|-- labels.txt # 类别名列表
+|-- train.txt # 训练集图片列表
+|-- val.txt # 验证集图片列表
+
+```
+
+* 解压后的表计测试图片的文件夹内容如下:
+
+一共有58张测试图片。
+
+```
+meter_test/
+|-- 20190822_105.jpg
+|-- 20190822_142.jpg
+|-- ... ...
+```
+
+## <h2 id="3">3 模型选择</h2>
+
+PaddleX提供了丰富的视觉模型,在目标检测中提供了RCNN和YOLO系列模型,在语义分割中提供了DeepLabV3P和BiSeNetV2等模型。
+
+因最终部署场景是本地化的服务器GPU端,算力相对充足,因此在本项目中采用精度和预测性能的PPYOLOV2进行表计检测。
+
+考虑到指针和刻度均为细小区域,我们采用精度更优的DeepLabV3P进行指针和刻度的分割。
+
+## <h2 id="4">4 表计检测模型训练</h2>
+
+本项目中采用精度和预测性能的PPYOLOV2进行表计检测。具体代码请参考[train_detection.py](./train_detection.py)。
+
+运行如下代码开始训练模型:
+
+```shell
+python train_detection.py
+```
+
+训练过程说明:
+
+定义数据预处理 -> 定义数据集路径 -> 初始化模型 -> 模型训练
+
+ * 定义数据预处理
+
+```python
+train_transforms = T.Compose([
+    T.MixupImage(mixup_epoch=250), T.RandomDistort(),
+    T.RandomExpand(im_padding_value=[123.675, 116.28, 103.53]), T.RandomCrop(),
+    T.RandomHorizontalFlip(), T.BatchRandomResize(
+        target_sizes=[320, 352, 384, 416, 448, 480, 512, 544, 576, 608],
+        interp='RANDOM'), T.Normalize(
+            mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
+])
+
+eval_transforms = T.Compose([
+    T.Resize(
+        608, interp='CUBIC'), T.Normalize(
+            mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
+])
+```
+
+
+ * 定义数据集路径
+
+```python
+
+# 下载和解压表计检测数据集,如果已经预先下载,可注释掉下面两行
+meter_det_dataset = 'https://bj.bcebos.com/paddlex/examples/meter_reader/datasets/meter_det.tar.gz'
+pdx.utils.download_and_decompress(meter_det_dataset, path='./')
+
+train_dataset = pdx.datasets.CocoDetection(
+    data_dir='meter_det/train/',
+    ann_file='meter_det/annotations/instance_train.json',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.CocoDetection(
+    data_dir='meter_det/test/',
+    ann_file='meter_det/annotations/instance_test.json',
+    transforms=eval_transforms)
+```
+
+ * 初始化模型
+
+```python
+num_classes = len(train_dataset.labels)
+model = pdx.models.PPYOLOv2(
+    num_classes=num_classes, backbone='ResNet50_vd_dcn')
+
+```
+
+* 模型训练
+
+```python
+model.train(
+    num_epochs=170,
+    train_dataset=train_dataset,
+    train_batch_size=8,
+    eval_dataset=eval_dataset,
+    pretrain_weights='COCO',
+    learning_rate=0.005 / 12,
+    warmup_steps=1000,
+    warmup_start_lr=0.0,
+    lr_decay_epochs=[105, 135, 150],
+    save_interval_epochs=5,
+    save_dir='output/ppyolov2_r50vd_dcn',
+    use_vdl=True)
+```
+
+## <h2 id="5">5 指针和刻度分割模型训练</h2>
+
+本项目中采用精度更优的DeepLabV3P进行指针和刻度的分割。具体代码请参考[train_segmentation.py](./train_segmentation.py)。
+
+运行如下代码开始训练模型:
+
+```shell
+python train_segmentation.py
+```
+
+训练过程说明:
+
+定义数据预处理 -> 定义数据集路径 -> 初始化模型 -> 模型训练
+
+* 定义数据预处理
+
+```python
+train_transforms = T.Compose([
+    T.Resize(target_size=512),
+    T.RandomHorizontalFlip(),
+    T.Normalize(
+        mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
+])
+
+eval_transforms = T.Compose([
+    T.Resize(target_size=512),
+    T.Normalize(
+        mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
+])
+```
+
+
+* 定义数据集路径
+
+```python
+# 下载和解压指针刻度分割数据集,如果已经预先下载,可注视掉下面两行
+meter_seg_dataset = 'https://bj.bcebos.com/paddlex/examples/meter_reader/datasets/meter_seg.tar.gz'
+pdx.utils.download_and_decompress(meter_seg_dataset, path='./')
+
+train_dataset = pdx.datasets.SegDataset(
+    data_dir='meter_seg',
+    file_list='meter_seg/train.txt',
+    label_list='meter_seg/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+
+eval_dataset = pdx.datasets.SegDataset(
+    data_dir='meter_seg',
+    file_list='meter_seg/val.txt',
+    label_list='meter_seg/labels.txt',
+    transforms=eval_transforms,
+    shuffle=False)
+
+```
+
+* 初始化模型
+
+```python
+num_classes = len(train_dataset.labels)
+model = pdx.models.DeepLabV3P(num_classes=num_classes, backbone='ResNet50_vd', use_mixed_loss=True)
+
+```
+
+* 模型训练
+
+```python
+model.train(
+    num_epochs=20,
+    train_dataset=train_dataset,
+    train_batch_size=4,
+    pretrain_weights='IMAGENET',
+    eval_dataset=eval_dataset,
+    learning_rate=0.1,
+    save_dir='output/deeplabv3p_r50vd')
+```
+
+## <h2 id="6">6 模型预测</h2>
+
+运行如下代码:
+
+```shell
+python reader_infer.py --det_model_dir output/ppyolov2_r50vd_dcn/best_model --seg_model_dir output/deeplabv3p_r50vd/best_model/ --image meter_det/test/20190822_105.jpg
+```
+
+则会在终端上输出信息:
+
+```
+Meter 1: 6.299999866666726
+Meter 2: 1.1057142840816332
+2021-06-26 12:17:14 [INFO]  The visualized result is saved at ./output/result/visualize_1624709834720.jpg
+
+```
+预测结果如下:
+
+<div align="center">
+<img src="./images/visualize_1624716128584.jpg"  width = "1000" />              </div>
+
+我们看下预测代码中的预测流程:
+
+图像解码 —> 检测表计 -> 过滤检测框 -> 提取检测框所在图像区域 -> 图像缩放 -> 指针和刻度分割 -> 读数后处理 -> 打印读数 -> 可视化预测结果
+
+```python
+def predict(self,
+            img_file,
+            save_dir='./',
+            use_erode=True,
+            erode_kernel=4,
+            score_threshold=0.5,
+            seg_batch_size=2):
+    """检测图像中的表盘,而后分割出各表盘中的指针和刻度,对分割结果进行读数后厨后得到各表盘的读数。
+
+
+        参数:
+            img_file (str):待预测的图片路径。
+            save_dir (str): 可视化结果的保存路径。
+            use_erode (bool, optional): 是否对分割预测结果做图像腐蚀。默认值:True。
+            erode_kernel (int, optional): 图像腐蚀的卷积核大小。默认值: 4。
+            score_threshold (float, optional): 用于滤除检测框的置信度阈值。默认值:0.5。
+            seg_batch_size (int, optional):分割模型前向推理一次时输入表盘图像的批量大小。默认值为:2。
+    """
+
+    img = self.decode(img_file)
+    det_results = self.detector.predict(img)
+    filtered_results = self.filter_bboxes(det_results, score_threshold)
+    sub_imgs = self.roi_crop(img, filtered_results)
+    sub_imgs = self.resize(sub_imgs, METER_SHAPE)
+    seg_results = self.seg_predict(self.segmenter, sub_imgs, seg_batch_size)
+    seg_results = self.erode(seg_results, erode_kernel)
+    meter_readings = self.get_meter_reading(seg_results)
+    self.print_meter_readings(meter_readings)
+    self.visualize(img, filtered_results, meter_readings, save_dir)
+
+```

二进制
dygraph/examples/meter_reader/images/MeterReader_Architecture.jpg


二进制
dygraph/examples/meter_reader/images/det_data.png


二进制
dygraph/examples/meter_reader/images/scene_introduce.jpg


二进制
dygraph/examples/meter_reader/images/seg_data.png


二进制
dygraph/examples/meter_reader/images/visualize_1624716128584.jpg


+ 598 - 0
dygraph/examples/meter_reader/reader_infer.py

@@ -0,0 +1,598 @@
+# coding: utf8
+# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import os.path as osp
+import numpy as np
+import math
+import cv2
+import argparse
+
+from paddlex import transforms as T
+import paddlex as pdx
+
+# 读数后处理中有把圆形表盘转成矩形的操作,矩形的宽即为圆形的外周长
+# 因此要求表盘图像大小为固定大小,这里设置为[512, 512]
+METER_SHAPE = [512, 512]  # 高x宽
+# 圆形表盘的中心点
+CIRCLE_CENTER = [256, 256]  # 高x宽
+# 圆形表盘的半径
+CIRCLE_RADIUS = 250
+# 圆周率
+PI = 3.1415926536
+# 在把圆形表盘转成矩形后矩形的高
+# 当前设置值约为半径的一半,原因是:圆形表盘的中心区域除了指针根部就是背景了
+# 我们只需要把外围的刻度、指针的尖部保存下来就可以定位出指针指向的刻度
+RECTANGLE_HEIGHT = 120
+# 矩形表盘的宽,即圆形表盘的外周长
+RECTANGLE_WIDTH = 1570
+# 当前案例中只使用了两种类型的表盘,第一种表盘的刻度根数为50
+# 第二种表盘的刻度根数为32。因此,我们通过预测的刻度根数来判断表盘类型
+# 刻度根数超过阈值的即为第一种,否则是第二种
+TYPE_THRESHOLD = 40
+# 两种表盘的配置信息,包含每根刻度的值,量程,单位
+METER_CONFIG = [{
+    'scale_interval_value': 25.0 / 50.0,
+    'range': 25.0,
+    'unit': "(MPa)"
+}, {
+    'scale_interval_value': 1.6 / 32.0,
+    'range': 1.6,
+    'unit': "(MPa)"
+}]
+# 分割模型预测类别id与类别名的对应关系
+SEG_CNAME2CLSID = {'background': 0, 'pointer': 1, 'scale': 2}
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(description='Meter Reader Infering')
+    parser.add_argument(
+        '--det_model_dir',
+        dest='det_model_dir',
+        help='The directory of the detection model',
+        type=str)
+    parser.add_argument(
+        '--seg_model_dir',
+        dest='seg_model_dir',
+        help='The directory of the segmentation model',
+        type=str)
+    parser.add_argument(
+        '--image_dir',
+        dest='image_dir',
+        help='The directory of images to be inferred',
+        type=str,
+        default=None)
+    parser.add_argument(
+        '--image',
+        dest='image',
+        help='The image to be inferred',
+        type=str,
+        default=None)
+    parser.add_argument(
+        '--use_erode',
+        dest='use_erode',
+        help='Whether erode the lable map predicted from a segmentation model',
+        action='store_true')
+    parser.add_argument(
+        '--erode_kernel',
+        dest='erode_kernel',
+        help='Erode kernel size',
+        type=int,
+        default=4)
+    parser.add_argument(
+        '--save_dir',
+        dest='save_dir',
+        help='The directory for saving the predicted results',
+        type=str,
+        default='./output/result')
+    parser.add_argument(
+        '--score_threshold',
+        dest='score_threshold',
+        help="Predicted bounding boxes whose scores are lower than this threshlod are filtered",
+        type=float,
+        default=0.5)
+    parser.add_argument(
+        '--seg_batch_size',
+        dest='seg_batch_size',
+        help="The number of images fed into the segmentation model during one forward propagation",
+        type=int,
+        default=2)
+
+    return parser.parse_args()
+
+
+def is_pic(img_name):
+    """判断是否是图片
+
+    参数:
+        img_name (str): 图片路径
+
+    返回:
+        flag (bool): 判断值。
+    """
+    valid_suffix = ['JPEG', 'jpeg', 'JPG', 'jpg', 'BMP', 'bmp', 'PNG', 'png']
+    suffix = img_name.split('.')[-1]
+    flag = True
+    if suffix not in valid_suffix:
+        flag = False
+    return flag
+
+
+class MeterReader:
+    """检测表盘的位置,分割各表盘内刻度和指针的位置,并根据分割结果计算出各表盘的读数
+
+    参数:
+        det_model_dir (str): 用于定位表盘的检测模型所在路径。
+        seg_model_dir (str): 用于分割刻度和指针的分割模型所在路径。
+
+    """
+
+    def __init__(self, det_model_dir, seg_model_dir):
+        if not osp.exists(det_model_dir):
+            raise Exception("Model path {} does not exist".format(
+                det_model_dir))
+        if not osp.exists(seg_model_dir):
+            raise Exception("Model path {} does not exist".format(
+                seg_model_dir))
+        self.detector = pdx.load_model(det_model_dir)
+        self.segmenter = pdx.load_model(seg_model_dir)
+
+    def decode(self, img_file):
+        """图像解码
+
+        参数:
+            img_file (str|np.array): 图像路径,或者是已解码的BGR图像数组。
+
+        返回:
+            img (np.array): BGR图像数组。
+        """
+
+        if isinstance(img_file, str):
+            img = cv2.imread(img_file).astype('float32')
+        else:
+            img = img_file.copy()
+        return img
+
+    def filter_bboxes(self, det_results, score_threshold):
+        """过滤置信度低于阈值的检测框
+
+        参数:
+            det_results (list[dict]): 检测模型预测接口的返回值。
+            score_threshold (float):置信度阈值。
+
+        返回:
+            filtered_results (list[dict]): 过滤后的检测狂。
+
+        """
+        filtered_results = list()
+        for res in det_results:
+            if res['score'] > score_threshold:
+                filtered_results.append(res)
+        return filtered_results
+
+    def roi_crop(self, img, det_results):
+        """抠取图像上各检测框的图像区域
+
+        参数:
+            img (np.array):BRG图像数组。
+            det_results (list[dict]): 检测模型预测接口的返回值。
+
+        返回:
+            sub_imgs (list[np.array]): 各检测框的图像区域。
+
+        """
+        sub_imgs = []
+        for res in det_results:
+            # Crop the bbox area
+            xmin, ymin, w, h = res['bbox']
+            xmin = max(0, int(xmin))
+            ymin = max(0, int(ymin))
+            xmax = min(img.shape[1], int(xmin + w - 1))
+            ymax = min(img.shape[0], int(ymin + h - 1))
+            sub_img = img[ymin:(ymax + 1), xmin:(xmax + 1), :]
+            sub_imgs.append(sub_img)
+        return sub_imgs
+
+    def resize(self, imgs, target_size, interp=cv2.INTER_LINEAR):
+        """图像缩放至固定大小
+
+        参数:
+            imgs (list[np.array]):批量BGR图像数组。
+            target_size (list|tuple):缩放后的图像大小,格式为[高, 宽]。
+            interp (int):图像差值方法。默认值为cv2.INTER_LINEAR。
+
+        返回:
+            resized_imgs (list[np.array]):缩放后的批量BGR图像数组。
+
+        """
+
+        resized_imgs = list()
+        for img in imgs:
+            img_shape = img.shape
+            scale_x = float(target_size[1]) / float(img_shape[1])
+            scale_y = float(target_size[0]) / float(img_shape[0])
+            resize_img = cv2.resize(
+                img, None, None, fx=scale_x, fy=scale_y, interpolation=interp)
+            resized_imgs.append(resize_img)
+        return resized_imgs
+
+    def seg_predict(self, segmenter, imgs, batch_size):
+        """分割模型完成预测
+
+        参数:
+            segmenter (pdx.seg.model):加载后的分割模型。
+            imgs (list[np.array]):待预测的输入BGR图像数组。
+            batch_size (int): 分割模型前向预测一次时输入图像的批量大小。
+
+        返回:
+            seg_results (list[dict]): 输入图像的预测结果。
+
+        """
+        seg_results = list()
+        num_imgs = len(imgs)
+        for i in range(0, num_imgs, batch_size):
+            batch = imgs[i:min(num_imgs, i + batch_size)]
+            result = segmenter.predict(batch)
+            seg_results.extend(result)
+        return seg_results
+
+    def erode(self, seg_results, erode_kernel):
+        """对分割模型预测结果中label_map做图像腐蚀操作
+
+        参数:
+            seg_results (list[dict]):分割模型的预测结果。
+            erode_kernel (int): 图像腐蚀的卷积核的大小。
+
+        返回:
+            eroded_results (list[dict]):对label_map进行腐蚀后的分割模型预测结果。
+
+        """
+        kernel = np.ones((erode_kernel, erode_kernel), np.uint8)
+        eroded_results = seg_results
+        for i in range(len(seg_results)):
+            eroded_results[i]['label_map'] = cv2.erode(
+                seg_results[i]['label_map'], kernel)
+        return eroded_results
+
+    def circle_to_rectangle(self, seg_results):
+        """将圆形表盘的预测结果label_map转换成矩形
+
+        圆形到矩形的计算方法:
+            因本案例中两种表盘的刻度起始值都在左下方,故以圆形的中心点为坐标原点,
+            从-y轴开始逆时针计算极坐标到x-y坐标的对应关系:
+              x = r + r * cos(theta)
+              y = r - r * sin(theta)
+            注意:
+                1. 因为是从-y轴开始逆时针计算,所以r * sin(theta)前有负号。
+                2. 还是因为从-y轴开始逆时针计算,所以矩形从上往下对应圆形从外到内,
+                   可以想象把圆形从-y轴切开再往左右拉平时,圆形的外围是上面,內围在下面。
+
+        参数:
+            seg_results (list[dict]):分割模型的预测结果。
+
+        返回值:
+            rectangle_meters (list[np.array]):矩形表盘的预测结果label_map。
+
+        """
+        rectangle_meters = list()
+        for i, seg_result in enumerate(seg_results):
+            label_map = seg_result['label_map']
+            # rectangle_meter的大小已经由预先设置的全局变量RECTANGLE_HEIGHT, RECTANGLE_WIDTH决定
+            rectangle_meter = np.zeros(
+                (RECTANGLE_HEIGHT, RECTANGLE_WIDTH), dtype=np.uint8)
+            for row in range(RECTANGLE_HEIGHT):
+                for col in range(RECTANGLE_WIDTH):
+                    theta = PI * 2 * (col + 1) / RECTANGLE_WIDTH
+                    # 矩形从上往下对应圆形从外到内
+                    rho = CIRCLE_RADIUS - row - 1
+                    y = int(CIRCLE_CENTER[0] + rho * math.cos(theta) + 0.5)
+                    x = int(CIRCLE_CENTER[1] - rho * math.sin(theta) + 0.5)
+                    rectangle_meter[row, col] = label_map[y, x]
+            rectangle_meters.append(rectangle_meter)
+        return rectangle_meters
+
+    def rectangle_to_line(self, rectangle_meters):
+        """从矩形表盘的预测结果中提取指针和刻度预测结果并沿高度方向压缩成线状格式。
+
+        参数:
+            rectangle_meters (list[np.array]):矩形表盘的预测结果label_map。
+
+        返回:
+            line_scales (list[np.array]):刻度的线状预测结果。
+            line_pointers (list[np.array]):指针的线状预测结果。
+
+        """
+        line_scales = list()
+        line_pointers = list()
+
+        for rectangle_meter in rectangle_meters:
+            height, width = rectangle_meter.shape[0:2]
+            line_scale = np.zeros((width), dtype=np.uint8)
+            line_pointer = np.zeros((width), dtype=np.uint8)
+            for col in range(width):
+                for row in range(height):
+                    if rectangle_meter[row, col] == SEG_CNAME2CLSID['pointer']:
+                        line_pointer[col] += 1
+                    elif rectangle_meter[row, col] == SEG_CNAME2CLSID['scale']:
+                        line_scale[col] += 1
+            line_scales.append(line_scale)
+            line_pointers.append(line_pointer)
+        return line_scales, line_pointers
+
+    def mean_binarization(self, data_list):
+        """对图像进行均值二值化操作
+
+        参数:
+            data_list (list[np.array]):待二值化的批量数组。
+
+        返回:
+            binaried_data_list (list[np.array]):二值化后的批量数组。
+
+        """
+        batch_size = len(data_list)
+        binaried_data_list = data_list
+        for i in range(batch_size):
+            mean_data = np.mean(data_list[i])
+            width = data_list[i].shape[0]
+            for col in range(width):
+                if data_list[i][col] < mean_data:
+                    binaried_data_list[i][col] = 0
+                else:
+                    binaried_data_list[i][col] = 1
+        return binaried_data_list
+
+    def locate_scale(self, line_scales):
+        """在线状预测结果中找到每根刻度的中心位置
+
+        参数:
+            line_scales (list[np.array]):批量的二值化后的刻度线状预测结果。
+
+        返回:
+            scale_locations (list[list]):各图像中每根刻度的中心位置。
+
+        """
+        batch_size = len(line_scales)
+        scale_locations = list()
+        for i in range(batch_size):
+            line_scale = line_scales[i]
+            width = line_scale.shape[0]
+            find_start = False
+            one_scale_start = 0
+            one_scale_end = 0
+            locations = list()
+            for j in range(width - 1):
+                if line_scale[j] > 0 and line_scale[j + 1] > 0:
+                    if find_start == False:
+                        one_scale_start = j
+                        find_start = True
+                if find_start:
+                    if line_scale[j] == 0 and line_scale[j + 1] == 0:
+                        one_scale_end = j - 1
+                        one_scale_location = (
+                            one_scale_start + one_scale_end) / 2
+                        locations.append(one_scale_location)
+                        one_scale_start = 0
+                        one_scale_end = 0
+                        find_start = False
+            scale_locations.append(locations)
+        return scale_locations
+
+    def locate_pointer(self, line_pointers):
+        """在线状预测结果中找到指针的中心位置
+
+        参数:
+            line_scales (list[np.array]):批量的指针线状预测结果。
+
+        返回:
+            scale_locations (list[list]):各图像中指针的中心位置。
+
+        """
+        batch_size = len(line_pointers)
+        pointer_locations = list()
+        for i in range(batch_size):
+            line_pointer = line_pointers[i]
+            find_start = False
+            pointer_start = 0
+            pointer_end = 0
+            location = 0
+            width = line_pointer.shape[0]
+            for j in range(width - 1):
+                if line_pointer[j] > 0 and line_pointer[j + 1] > 0:
+                    if find_start == False:
+                        pointer_start = j
+                        find_start = True
+                if find_start:
+                    if line_pointer[j] == 0 and line_pointer[j + 1] == 0:
+                        pointer_end = j - 1
+                        location = (pointer_start + pointer_end) / 2
+                        find_start = False
+                        break
+            pointer_locations.append(location)
+        return pointer_locations
+
+    def get_relative_location(self, scale_locations, pointer_locations):
+        """找到指针指向了第几根刻度
+
+        参数:
+            scale_locations (list[list]):批量的每根刻度的中心点位置。
+            pointer_locations (list[list]):批量的指针的中心点位置。
+
+        返回:
+            pointed_scales (list[dict]):每个表的结果组成的list。每个表的结果由字典表示,
+                字典有两个关键词:'num_scales'、'pointed_scale',分别表示预测的刻度根数、
+                预测的指针指向了第几根刻度。
+
+        """
+
+        pointed_scales = list()
+        for scale_location, pointer_location in zip(scale_locations,
+                                                    pointer_locations):
+            num_scales = len(scale_location)
+            pointed_scale = -1
+            if num_scales > 0:
+                for i in range(num_scales - 1):
+                    if scale_location[
+                            i] <= pointer_location and pointer_location < scale_location[
+                                i + 1]:
+                        pointed_scale = i + (
+                            pointer_location - scale_location[i]
+                        ) / (scale_location[i + 1] - scale_location[i] + 1e-05
+                             ) + 1
+            result = {'num_scales': num_scales, 'pointed_scale': pointed_scale}
+            pointed_scales.append(result)
+        return pointed_scales
+
+    def calculate_reading(self, pointed_scales):
+        """根据刻度的间隔值和指针指向的刻度根数计算表盘的读数
+        """
+        readings = list()
+        batch_size = len(pointed_scales)
+        for i in range(batch_size):
+            pointed_scale = pointed_scales[i]
+            # 刻度根数大于阈值的为第一种表盘
+            if pointed_scale['num_scales'] > TYPE_THRESHOLD:
+                reading = pointed_scale['pointed_scale'] * METER_CONFIG[0][
+                    'scale_interval_value']
+            else:
+                reading = pointed_scale['pointed_scale'] * METER_CONFIG[1][
+                    'scale_interval_value']
+            readings.append(reading)
+
+        return readings
+
+    def get_meter_reading(self, seg_results):
+        """对分割结果进行读数后处理得到各表盘的读数
+
+        参数:
+            seg_results (list[dict]): 分割模型的预测结果。
+
+        返回:
+            meter_readings (list[dcit]): 各表盘的读数。
+
+        """
+
+        rectangle_meters = self.circle_to_rectangle(seg_results)
+        line_scales, line_pointers = self.rectangle_to_line(rectangle_meters)
+        binaried_scales = self.mean_binarization(line_scales)
+        binaried_pointers = self.mean_binarization(line_pointers)
+        scale_locations = self.locate_scale(binaried_scales)
+        pointer_locations = self.locate_pointer(binaried_pointers)
+        pointed_scales = self.get_relative_location(scale_locations,
+                                                    pointer_locations)
+        meter_readings = self.calculate_reading(pointed_scales)
+        return meter_readings
+
+    def print_meter_readings(self, meter_readings):
+        """打印各表盘的读数
+
+        参数:
+            meter_readings (list[dict]):各表盘的读数
+        """
+        for i in range(len(meter_readings)):
+            print("Meter {}: {}".format(i + 1, meter_readings[i]))
+
+    def visualize(self, img, det_results, meter_readings, save_dir="./"):
+        """可视化图像中各表盘的位置和读数
+
+        参数:
+            img (str|np.array): 图像路径,或者是已解码的BGR图像数组。
+            det_results (dict): 检测模型的预测结果。
+            meter_readings (list): 各表盘的读数。
+            save_dir (str):可视化后的图片保存路径。
+
+        """
+        vis_results = list()
+        for i, res in enumerate(det_results):
+            # 将检测结果中的关键词`score`替换成读数,就可以调用pdx.det.visualize画图了
+            res['score'] = meter_readings[i]
+            vis_results.append(res)
+        # 检测结果可视化时会滤除score低于threshold的框,这里读数都是>=-1的,所以设置thresh=-1
+        pdx.det.visualize(img, vis_results, threshold=-1, save_dir=save_dir)
+
+    def predict(self,
+                img_file,
+                save_dir='./',
+                use_erode=True,
+                erode_kernel=4,
+                score_threshold=0.5,
+                seg_batch_size=2):
+        """Detect meters in a image, segment scales and points in these meters, the postprocess are
+        done to provide a digital readout according to scale and point location.
+
+        Args:
+            im_file (str):  the path of a image to be predicted.
+            save_dir (str): the directory to save the visual prediction. Default: './'.
+            use_erode (bool, optional): whether to do image erosion by using a specific structuring element for
+                the label map output from the segmenter. Default: True.
+            erode_kernel (int, optional): structuring element used for erosion. Default: 4.
+            score_threshold (float, optional): detected meters whose scores are not lower than `score_threshold`
+                will be fed into the following segmenter. Default: 0.5.
+            seg_batch_size (int, optional): batch size of meters when do segmentation. Default: 2.
+
+        """
+        """检测图像中的表盘,而后分割出各表盘中的指针和刻度,对分割结果进行读数后厨后得到各表盘的读数。
+
+
+        参数:
+            img_file (str):待预测的图片路径。
+            save_dir (str): 可视化结果的保存路径。
+            use_erode (bool, optional): 是否对分割预测结果做图像腐蚀。默认值:True。
+            erode_kernel (int, optional): 图像腐蚀的卷积核大小。默认值: 4。
+            score_threshold (float, optional): 用于滤除检测框的置信度阈值。默认值:0.5。
+            seg_batch_size (int, optional):分割模型前向推理一次时输入表盘图像的批量大小。默认值为:2。
+        """
+
+        img = self.decode(img_file)
+        det_results = self.detector.predict(img)
+        filtered_results = self.filter_bboxes(det_results, score_threshold)
+        sub_imgs = self.roi_crop(img, filtered_results)
+        sub_imgs = self.resize(sub_imgs, METER_SHAPE)
+        seg_results = self.seg_predict(self.segmenter, sub_imgs,
+                                       seg_batch_size)
+        seg_results = self.erode(seg_results, erode_kernel)
+        meter_readings = self.get_meter_reading(seg_results)
+        self.print_meter_readings(meter_readings)
+        self.visualize(img, filtered_results, meter_readings, save_dir)
+
+
+def infer(args):
+    image_lists = list()
+    if args.image is not None:
+        if not osp.exists(args.image):
+            raise Exception("Image {} does not exist.".format(args.image))
+        if not is_pic(args.image):
+            raise Exception("{} is not a picture.".format(args.image))
+        image_lists.append(args.image)
+    elif args.image_dir is not None:
+        if not osp.exists(args.image_dir):
+            raise Exception("Directory {} does not exist.".format(
+                args.image_dir))
+        for im_file in os.listdir(args.image_dir):
+            if not is_pic(im_file):
+                continue
+            im_file = osp.join(args.image_dir, im_file)
+            image_lists.append(im_file)
+
+    meter_reader = MeterReader(args.det_model_dir, args.seg_model_dir)
+    if len(image_lists) > 0:
+        for image in image_lists:
+            meter_reader.predict(image, args.save_dir, args.use_erode,
+                                 args.erode_kernel, args.score_threshold,
+                                 args.seg_batch_size)
+
+
+if __name__ == '__main__':
+    args = parse_args()
+    infer(args)

+ 55 - 0
dygraph/examples/meter_reader/train_detection.py

@@ -0,0 +1,55 @@
+import paddlex as pdx
+from paddlex import transforms as T
+
+# 定义训练和验证时的transforms
+# API说明:https://github.com/PaddlePaddle/PaddleX/blob/release/2.0-rc/paddlex/cv/transforms/operators.py
+train_transforms = T.Compose([
+    T.MixupImage(mixup_epoch=250), T.RandomDistort(),
+    T.RandomExpand(im_padding_value=[123.675, 116.28, 103.53]), T.RandomCrop(),
+    T.RandomHorizontalFlip(), T.BatchRandomResize(
+        target_sizes=[320, 352, 384, 416, 448, 480, 512, 544, 576, 608],
+        interp='RANDOM'), T.Normalize(
+            mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
+])
+
+eval_transforms = T.Compose([
+    T.Resize(
+        608, interp='CUBIC'), T.Normalize(
+            mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
+])
+
+# 下载和解压表计检测数据集,如果已经预先下载,可注释掉下面两行
+meter_det_dataset = 'https://bj.bcebos.com/paddlex/examples/meter_reader/datasets/meter_det.tar.gz'
+pdx.utils.download_and_decompress(meter_det_dataset, path='./')
+
+# 定义训练和验证所用的数据集
+# API说明:https://github.com/PaddlePaddle/PaddleX/blob/develop/dygraph/paddlex/cv/datasets/coco.py#L26
+train_dataset = pdx.datasets.CocoDetection(
+    data_dir='meter_det/train/',
+    ann_file='meter_det/annotations/instance_train.json',
+    transforms=train_transforms,
+    shuffle=True)
+eval_dataset = pdx.datasets.CocoDetection(
+    data_dir='meter_det/test/',
+    ann_file='meter_det/annotations/instance_test.json',
+    transforms=eval_transforms)
+
+# 初始化模型,并进行训练
+# 可使用VisualDL查看训练指标,参考https://github.com/PaddlePaddle/PaddleX/tree/release/2.0-rc/tutorials/train#visualdl可视化训练指标
+num_classes = len(train_dataset.labels)
+model = pdx.det.PPYOLOv2(num_classes=num_classes, backbone='ResNet50_vd_dcn')
+
+# API说明:https://github.com/PaddlePaddle/PaddleX/blob/release/2.0-rc/paddlex/cv/models/detector.py#L155
+# 各参数介绍与调整说明:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html
+model.train(
+    num_epochs=170,
+    train_dataset=train_dataset,
+    train_batch_size=8,
+    eval_dataset=eval_dataset,
+    pretrain_weights='COCO',
+    learning_rate=0.005 / 12,
+    warmup_steps=1000,
+    warmup_start_lr=0.0,
+    lr_decay_epochs=[105, 135, 150],
+    save_interval_epochs=5,
+    save_dir='output/ppyolov2_r50vd_dcn')

+ 54 - 0
dygraph/examples/meter_reader/train_segmentation.py

@@ -0,0 +1,54 @@
+import paddlex as pdx
+from paddlex import transforms as T
+
+# 定义训练和验证时的transforms
+# API说明:https://github.com/PaddlePaddle/PaddleX/blob/release/2.0-rc/paddlex/cv/transforms/operators.py
+train_transforms = T.Compose([
+    T.Resize(target_size=512),
+    T.RandomHorizontalFlip(),
+    T.Normalize(
+        mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
+])
+
+eval_transforms = T.Compose([
+    T.Resize(target_size=512),
+    T.Normalize(
+        mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5]),
+])
+
+# 下载和解压指针刻度分割数据集,如果已经预先下载,可注视掉下面两行
+meter_seg_dataset = 'https://bj.bcebos.com/paddlex/examples/meter_reader/datasets/meter_seg.tar.gz'
+pdx.utils.download_and_decompress(meter_seg_dataset, path='./')
+
+# 定义训练和验证所用的数据集
+# API说明:https://github.com/PaddlePaddle/PaddleX/blob/release/2.0-rc/paddlex/cv/datasets/seg_dataset.py#L22
+train_dataset = pdx.datasets.SegDataset(
+    data_dir='meter_seg',
+    file_list='meter_seg/train.txt',
+    label_list='meter_seg/labels.txt',
+    transforms=train_transforms,
+    shuffle=True)
+
+eval_dataset = pdx.datasets.SegDataset(
+    data_dir='meter_seg',
+    file_list='meter_seg/val.txt',
+    label_list='meter_seg/labels.txt',
+    transforms=eval_transforms,
+    shuffle=False)
+
+# 初始化模型,并进行训练
+# 可使用VisualDL查看训练指标,参考https://github.com/PaddlePaddle/PaddleX/tree/release/2.0-rc/tutorials/train#visualdl可视化训练指标
+num_classes = len(train_dataset.labels)
+model = pdx.seg.DeepLabV3P(
+    num_classes=num_classes, backbone='ResNet50_vd', use_mixed_loss=True)
+
+# API说明:https://github.com/PaddlePaddle/PaddleX/blob/release/2.0-rc/paddlex/cv/models/segmenter.py#L150
+# 各参数介绍与调整说明:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html
+model.train(
+    num_epochs=20,
+    train_dataset=train_dataset,
+    train_batch_size=4,
+    pretrain_weights='IMAGENET',
+    eval_dataset=eval_dataset,
+    learning_rate=0.1,
+    save_dir='output/deeplabv3p_r50vd')

+ 2 - 0
dygraph/paddlex/cv/models/base.py

@@ -56,6 +56,7 @@ class BaseModel:
         self.pruning_ratios = None
         self.quantizer = None
         self.quant_config = None
+        self.fixed_input_shape = None
 
     def net_initialize(self,
                        pretrain_weights=None,
@@ -130,6 +131,7 @@ class BaseModel:
 
         info['_Attributes']['num_classes'] = self.num_classes
         info['_Attributes']['labels'] = self.labels
+        info['_Attributes']['fixed_input_shape'] = self.fixed_input_shape
 
         try:
             primary_metric_key = list(self.eval_metrics.keys())[0]

+ 5 - 2
dygraph/paddlex/cv/models/classifier.py

@@ -82,10 +82,11 @@ class BaseClassifier(BaseModel):
     def _get_test_inputs(self, image_shape):
         if image_shape is not None:
             if len(image_shape) == 2:
-                image_shape = [None, 3] + image_shape
+                image_shape = [1, 3] + image_shape
             self._fix_transforms_shape(image_shape[-2:])
         else:
             image_shape = [None, 3, -1, -1]
+        self.fixed_input_shape = image_shape
         input_spec = [
             InputSpec(
                 shape=image_shape, name='image', dtype='float32')
@@ -570,7 +571,7 @@ class AlexNet(BaseClassifier):
                 'Please check image shape after transforms is [3, 224, 224], if not, fixed_input_shape '
                 + 'should be specified manually.')
         self._fix_transforms_shape(image_shape[-2:])
-
+        self.fixed_input_shape = image_shape
         input_spec = [
             InputSpec(
                 shape=image_shape, name='image', dtype='float32')
@@ -778,6 +779,7 @@ class ShuffleNetV2(BaseClassifier):
                 'Please check image shape after transforms is [3, 224, 224], if not, fixed_input_shape '
                 + 'should be specified manually.')
         self._fix_transforms_shape(image_shape[-2:])
+        self.fixed_input_shape = image_shape
         input_spec = [
             InputSpec(
                 shape=image_shape, name='image', dtype='float32')
@@ -804,6 +806,7 @@ class ShuffleNetV2_swish(BaseClassifier):
                 'Please check image shape after transforms is [3, 224, 224], if not, fixed_input_shape '
                 + 'should be specified manually.')
         self._fix_transforms_shape(image_shape[-2:])
+        self.fixed_input_shape = image_shape
         input_spec = [
             InputSpec(
                 shape=image_shape, name='image', dtype='float32')

+ 8 - 20
dygraph/paddlex/cv/models/detector.py

@@ -75,7 +75,7 @@ class BaseDetector(BaseModel):
 
     def _check_image_shape(self, image_shape):
         if len(image_shape) == 2:
-            image_shape = [None, 3] + image_shape
+            image_shape = [1, 3] + image_shape
             if image_shape[-2] % 32 > 0 or image_shape[-1] % 32 > 0:
                 raise Exception(
                     "Height and width in fixed_input_shape must be a multiple of 32, but received {}.".
@@ -88,6 +88,7 @@ class BaseDetector(BaseModel):
             self._fix_transforms_shape(image_shape[-2:])
         else:
             image_shape = [None, 3, -1, -1]
+        self.fixed_input_shape = image_shape
 
         return self._define_input_spec(image_shape)
 
@@ -1034,6 +1035,7 @@ class FasterRCNN(BaseDetector):
                 self.test_transforms.transforms.append(
                     Padding(im_padding_value=[0., 0., 0.]))
 
+        self.fixed_input_shape = image_shape
         return self._define_input_spec(image_shape)
 
 
@@ -1428,14 +1430,10 @@ class PPYOLOv2(YOLOv3):
 
     def _get_test_inputs(self, image_shape):
         if image_shape is not None:
-            if len(image_shape) == 2:
-                image_shape = [None, 3] + image_shape
-            if image_shape[-2] % 32 > 0 or image_shape[-1] % 32 > 0:
-                raise Exception(
-                    "Height and width in fixed_input_shape must be a multiple of 32, but recieved is {}.".
-                    format(image_shape[-2:]))
+            image_shape = self._check_image_shape(image_shape)
             self._fix_transforms_shape(image_shape[-2:])
         else:
+            image_shape = [None, 3, 608, 608]
             logging.warning(
                 '[Important!!!] When exporting inference model for {},'.format(
                     self.__class__.__name__) +
@@ -1443,20 +1441,9 @@ class PPYOLOv2(YOLOv3):
                 +
                 'Please check image shape after transforms is [3, 608, 608], if not, fixed_input_shape '
                 + 'should be specified manually.')
-            image_shape = [None, 3, 608, 608]
 
-        input_spec = [{
-            "image": InputSpec(
-                shape=image_shape, name='image', dtype='float32'),
-            "im_shape": InputSpec(
-                shape=[image_shape[0], 2], name='im_shape', dtype='float32'),
-            "scale_factor": InputSpec(
-                shape=[image_shape[0], 2],
-                name='scale_factor',
-                dtype='float32')
-        }]
-
-        return input_spec
+        self.fixed_input_shape = image_shape
+        return self._define_input_spec(image_shape)
 
 
 class MaskRCNN(BaseDetector):
@@ -1755,5 +1742,6 @@ class MaskRCNN(BaseDetector):
             if self.with_fpn:
                 self.test_transforms.transforms.append(
                     Padding(im_padding_value=[0., 0., 0.]))
+        self.fixed_input_shape = image_shape
 
         return self._define_input_spec(image_shape)

+ 2 - 1
dygraph/paddlex/cv/models/segmenter.py

@@ -82,10 +82,11 @@ class BaseSegmenter(BaseModel):
     def _get_test_inputs(self, image_shape):
         if image_shape is not None:
             if len(image_shape) == 2:
-                image_shape = [None, 3] + image_shape
+                image_shape = [1, 3] + image_shape
             self._fix_transforms_shape(image_shape[-2:])
         else:
             image_shape = [None, 3, -1, -1]
+        self.fixed_input_shape = image_shape
         input_spec = [
             InputSpec(
                 shape=image_shape, name='image', dtype='float32')

+ 1 - 1
dygraph/paddlex/cv/transforms/operators.py

@@ -943,7 +943,7 @@ class Padding(Transform):
             assert offsets, 'if pad_mode is -1, offsets should not be None'
 
         self.target_size = target_size
-        self.coarsest_stride = size_divisor
+        self.size_divisor = size_divisor
         self.pad_mode = pad_mode
         self.offsets = offsets
         self.im_padding_value = im_padding_value