README.md 13.7 KB
Newer Older
F
FlyingQianMM 已提交
1 2 3 4
# MeterReader表计读数

本案例基于PaddleX实现对传统机械式指针表计的检测与自动读数功能,开放表计数据和预训练模型,并提供在windows系统的服务器端以及linux系统的jetson嵌入式设备上的部署指南。

F
FlyingQianMM 已提交
5
## 目录
F
FlyingQianMM 已提交
6

F
FlyingQianMM 已提交
7 8 9 10 11
* [读数流程](#1)
* [表计数据和预训练模型](#2)
* [快速体验表盘读数](#3)
* [推理部署](#4)
* [模型训练](#5)
F
FlyingQianMM 已提交
12

F
FlyingQianMM 已提交
13 14

## <h2 id="1">读数流程</h2>
F
FlyingQianMM 已提交
15 16 17 18 19 20 21 22 23 24

表计读数共分为三个步骤完成:第一步使用目标检测模型检测出图像中的表具,第二步使用语义分割模型将各表具的指针和刻度分割出来,第三步根据指针的相对位置和预知的量程计算出各表计的读数。

![MeterReader_Architecture](image/MeterReader_Architecture.jpg)

* 目标检测:由于本案例中没有面积较小的表计,所以目标检测模型选择性能更优的**YOLOv3**。考虑到本案例主要在有GPU的设备上部署,所以骨干网路选择精度更高的**DarkNet53**
* 语义分割:考虑到刻度和指针均为细小区域,语义分割模型选择效果更好的**DeepLapv3**
* 读数计算后处理:首先,对语义分割的预测类别图进行图像腐蚀操作,以达到刻度细分的目的。然后把环形的表盘展开为矩形图像,根据图像中类别信息生成一维的刻度数组和一维的指针数组。接着计算刻度数组的均值,用均值对刻度数组进行二值化操作。最后定位出指针相对刻度的位置,根据刻度的根数判断表盘的类型以此获取表盘的量程,将指针相对位置与量程做乘积得到表盘的读数。


F
FlyingQianMM 已提交
25
## <h2 id="2">表计数据和预训练模型</h2>
F
FlyingQianMM 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39

本案例开放了表计测试图片,用于体验表计读数的预测推理全流程。还开放了表计检测数据集、指针和刻度分割数据集,用户可以使用这些数据集重新训练模型。

| 表计测试图片                                                 | 表计检测数据集                                               | 指针和刻度分割数据集                                         |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| [meter_test](https://bj.bcebos.com/paddlex/meterreader/datasets/meter_test.tar.gz) | [meter_det](https://bj.bcebos.com/paddlex/meterreader/datasets/meter_det.tar.gz) | [meter_seg](https://bj.bcebos.com/paddlex/meterreader/datasets/meter_seg.tar.gz) |

本案例开放了预先训练好的检测模型和语义分割模型,可以使用这些模型快速体验表计读数全流程,也可以直接将这些模型部署在服务器端或jetson嵌入式设备上进行推理预测。

| 表计检测模型                                                 | 指针和刻度分割模型                                           |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| [meter_det_inference_model](https://bj.bcebos.com/paddlex/meterreader/models/meter_det_inference_model.tar.gz) | [meter_seg_inference_model](https://bj.bcebos.com/paddlex/meterreader/models/meter_seg_inference_model.tar.gz) |


F
FlyingQianMM 已提交
40
## <h2 id="3">快速体验表盘读数</h2>
F
FlyingQianMM 已提交
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

可以使用本案例提供的预训练模型快速体验表计读数的自动预测全流程。如果不需要预训练模型,可以跳转至小节`模型训练` 重新训练模型。

#### 前置依赖

* Paddle paddle >= 1.8.0
* Python >= 3.5
* PaddleX >= 1.0.0

安装的相关问题参考[PaddleX安装](https://paddlex.readthedocs.io/zh_CN/latest/install.html)

#### 测试表计读数

1. 下载PaddleX源码:

```
git clone https://github.com/PaddlePaddle/PaddleX
```

2. 预测执行文件位于`PaddleX/examples/meter_reader/`,进入该目录:

```
cd PaddleX/examples/meter_reader/
```

预测执行文件为`reader_infer.py`,其主要参数说明如下:


| 参数    | 说明   |
| ---- | ---- |
|  detector_dir    | 表计检测模型路径     |
|	segmenter_dir		 | 指针和刻度分割模型路径|
|	image            | 待预测的图片路径  |
|  image_dir       | 存储待预测图片的文件夹路径 |
| save_dir	| 保存可视化结果的路径, 默认值为"output"|
| score_threshold | 检测模型输出结果中,预测得分低于该阈值的框将被滤除,默认值为0.5|
| seg_batch_size | 分割的批量大小,默认为2 |
| seg_thread_num	| 分割预测的线程数,默认为cpu处理器个数 |
| use_camera | 是否使用摄像头采集图片,默认为False |
| use_erode | 是否使用图像腐蚀对分割预测图进行细分,默认为False |
| erode_kernel | 图像腐蚀操作时的卷积核大小,默认值为4 |

3. 预测

若要使用GPU,则指定GPU卡号(以0号卡为例):

```shell
export CUDA_VISIBLE_DEVICES=0
```
若不使用GPU,则将CUDA_VISIBLE_DEVICES指定为空:
```shell
export CUDA_VISIBLE_DEVICES=
```

* 预测单张图片

```shell
python3 reader_infer.py --detector_dir /path/to/det_inference_model --segmenter_dir /path/to/seg_inference_model --image /path/to/meter_test/20190822_168.jpg --save_dir ./output --use_erode
```

* 预测多张图片

```shell
python3 reader_infer.py --detector_dir /path/to/det_inference_model --segmenter_dir /path/to/seg_inference_model --image_dir /path/to/meter_test --save_dir ./output --use_erode
```

* 开启摄像头预测

```shell
python3 reader_infer.py --detector_dir /path/to/det_inference_model --segmenter_dir /path/to/seg_inference_model --save_dir ./output --use_erode --use_camera
```

F
FlyingQianMM 已提交
113
## <h2 id="4">推理部署</h2>
F
FlyingQianMM 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135

### Windows系统的服务器端安全部署

#### c++部署

1. 下载PaddleX源码:

```
git clone https://github.com/PaddlePaddle/PaddleX
```

2.`PaddleX\examples\meter_reader\deploy\cpp`下的`meter`文件夹和`CMakeList.txt`拷贝至`PaddleX\deploy\cpp`目录下,拷贝之前可以将`PaddleX\deploy\cpp`下原本的`CMakeList.txt`做好备份。

3. 按照[Windows平台部署](https://github.com/PaddlePaddle/PaddleX/blob/develop/docs/tutorials/deploy/deploy_server/deploy_cpp/deploy_cpp_win_vs2019.md)中的Step2至Step4完成C++预测代码的编译。

4. 编译成功后,可执行文件在`out\build\x64-Release`目录下,打开`cmd`,并切换到该目录:

   ```
   cd PaddleX\deploy\cpp\out\build\x64-Release
   ```

   预测程序为paddle_inference\meter.exe,其主要命令参数说明如下:
F
FlyingQianMM 已提交
136

F
FlyingQianMM 已提交
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
   | 参数    | 说明   |
   | ---- | ---- |
   |  det_model_dir    | 表计检测模型路径     |
   |	seg_model_dir		 | 指针和刻度分割模型路径|
   |	image            | 待预测的图片路径  |
   |  image_list       | 按行存储图片路径的.txt文件 |
   | use_gpu	| 是否使用 GPU 预测, 支持值为0或1(默认值为0)|
   | gpu_id	| GPU 设备ID, 默认值为0 |
   | save_dir	| 保存可视化结果的路径, 默认值为"output"|
   | det_key	| 检测模型加密过程中产生的密钥信息,默认值为""表示加载的是未加密的检测模型 |
   | seg_key	| 分割模型加密过程中产生的密钥信息,默认值为""表示加载的是未加密的分割模型 |
   | seg_batch_size | 分割的批量大小,默认为2 |
   | thread_num	| 分割预测的线程数,默认为cpu处理器个数 |
   | use_camera | 是否使用摄像头采集图片,支持值为0或1(默认值为0) |
   | camera_id | 摄像头设备ID,默认值为0 |
   | use_erode | 是否使用图像腐蚀对分割预测图进行去噪,支持值为0或1(默认值为1) |
   | erode_kernel | 图像腐蚀操作时的卷积核大小,默认值为4 |


5. 推理预测:

F
FlyingQianMM 已提交
158
  用于部署推理的模型应为inference格式,本案例提供的预训练模型均为inference格式,如若是重新训练的模型,需参考[导出inference模型](https://paddlex.readthedocs.io/zh_CN/latest/tutorials/deploy/deploy_server/deploy_python.html#inference)将模型导出为inference格式。
F
FlyingQianMM 已提交
159 160

  * 使用未加密的模型对单张图片做预测
F
FlyingQianMM 已提交
161

F
FlyingQianMM 已提交
162 163 164
  ```shell
  .\paddlex_inference\meter.exe --det_model_dir=\path\to\det_inference_model --seg_model_dir=\path\to\seg_inference_model --image=\path\to\meter_test\20190822_168.jpg --use_gpu=1 --use_erode=1 --save_dir=output
  ```
F
FlyingQianMM 已提交
165

F
FlyingQianMM 已提交
166
  * 使用未加密的模型对图像列表做预测
F
FlyingQianMM 已提交
167

F
FlyingQianMM 已提交
168 169 170
  ```shell
  .\paddlex_inference\meter.exe --det_model_dir=\path\to\det_inference_model --seg_model_dir=\path\to\seg_inference_model --image_list=\path\to\meter_test\image_list.txt --use_gpu=1 --use_erode=1 --save_dir=output
  ```
F
FlyingQianMM 已提交
171

F
FlyingQianMM 已提交
172
  * 使用未加密的模型开启摄像头做预测
F
FlyingQianMM 已提交
173

F
FlyingQianMM 已提交
174 175 176
  ```shell
  .\paddlex_inference\meter.exe --det_model_dir=\path\to\det_inference_model --seg_model_dir=\path\to\seg_inference_model --use_camera=1 --use_gpu=1 --use_erode=1 --save_dir=output
  ```
F
FlyingQianMM 已提交
177

F
FlyingQianMM 已提交
178
  * 使用加密后的模型对单张图片做预测
F
FlyingQianMM 已提交
179

F
FlyingQianMM 已提交
180
  如果未对模型进行加密,请参考[加密PaddleX模型](https://github.com/PaddlePaddle/PaddleX/blob/develop/docs/tutorials/deploy/deploy_server/encryption.html#paddlex)对模型进行加密。例如加密后的检测模型所在目录为`\path\to\encrypted_det_inference_model`,密钥为`yEBLDiBOdlj+5EsNNrABhfDuQGkdcreYcHcncqwdbx0=`;加密后的分割模型所在目录为`\path\to\encrypted_seg_inference_model`,密钥为`DbVS64I9pFRo5XmQ8MNV2kSGsfEr4FKA6OH9OUhRrsY=`
F
FlyingQianMM 已提交
181

F
FlyingQianMM 已提交
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
  ```shell
  .\paddlex_inference\meter.exe --det_model_dir=\path\to\encrypted_det_inference_model --seg_model_dir=\path\to\encrypted_seg_inference_model --image=\path\to\test.jpg --use_gpu=1 --use_erode=1 --save_dir=output --det_key yEBLDiBOdlj+5EsNNrABhfDuQGkdcreYcHcncqwdbx0= --seg_key DbVS64I9pFRo5XmQ8MNV2kSGsfEr4FKA6OH9OUhRrsY=
  ```

### Linux系统的jeton嵌入式设备安全部署

#### c++部署

1. 下载PaddleX源码:

```
git clone https://github.com/PaddlePaddle/PaddleX
```

2.`PaddleX/examples/meter_readerdeploy/cpp`下的`meter`文件夹和`CMakeList.txt`拷贝至`PaddleX/deploy/cpp`目录下,拷贝之前可以将`PaddleX/deploy/cpp`下原本的`CMakeList.txt`做好备份。

3. 按照[Nvidia-Jetson开发板部署]()中的Step2至Step3完成C++预测代码的编译。

4. 编译成功后,可执行程为`build/meter/detector`,其主要命令参数说明如下:
F
FlyingQianMM 已提交
201 202
	
  | 参数    | 说明   |
F
FlyingQianMM 已提交
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
  | ---- | ---- |
  |  det_model_dir    | 表计检测模型路径     |
  |	seg_model_dir		 | 指针和刻度分割模型路径|
  |	image            | 待预测的图片路径  |
  |  image_list       | 按行存储图片路径的.txt文件 |
  | use_gpu	| 是否使用 GPU 预测, 支持值为0或1(默认值为0)|
  | gpu_id	| GPU 设备ID, 默认值为0 |
  | save_dir	| 保存可视化结果的路径, 默认值为"output"|
  | det_key	| 检测模型加密过程中产生的密钥信息,默认值为""表示加载的是未加密的检测模型 |
  | seg_key	| 分割模型加密过程中产生的密钥信息,默认值为""表示加载的是未加密的分割模型 |
  | seg_batch_size | 分割的批量大小,默认为2 |
  | thread_num	| 分割预测的线程数,默认为cpu处理器个数 |
  | use_camera | 是否使用摄像头采集图片,支持值为0或1(默认值为0) |
  | camera_id | 摄像头设备ID,默认值为0 |
  | use_erode | 是否使用图像腐蚀对分割预测图进行细分,支持值为0或1(默认值为1) |
  | erode_kernel | 图像腐蚀操作时的卷积核大小,默认值为4 |
F
FlyingQianMM 已提交
219

F
FlyingQianMM 已提交
220 221 222 223 224
5. 推理预测:

  用于部署推理的模型应为inference格式,本案例提供的预训练模型均为inference格式,如若是重新训练的模型,需参考[导出inference模型]()将模型导出为inference格式。

  * 使用未加密的模型对单张图片做预测
F
FlyingQianMM 已提交
225

F
FlyingQianMM 已提交
226 227 228
  ```shell
  ./build/meter/meter --det_model_dir=/path/to/det_inference_model --seg_model_dir=/path/to/seg_inference_model --image=/path/to/meter_test/20190822_168.jpg --use_gpu=1 --use_erode=1 --save_dir=output
  ```
F
FlyingQianMM 已提交
229

F
FlyingQianMM 已提交
230
  * 使用未加密的模型对图像列表做预测
F
FlyingQianMM 已提交
231

F
FlyingQianMM 已提交
232 233 234
  ```shell
  ./build/meter/meter --det_model_dir=/path/to/det_inference_model --seg_model_dir=/path/to/seg_inference_model --image_list=/path/to/image_list.txt --use_gpu=1 --use_erode=1 --save_dir=output
  ```
F
FlyingQianMM 已提交
235

F
FlyingQianMM 已提交
236
  * 使用未加密的模型开启摄像头做预测
F
FlyingQianMM 已提交
237

F
FlyingQianMM 已提交
238 239 240 241 242
  ```shell
  ./build/meter/meter --det_model_dir=/path/to/det_inference_model --seg_model_dir=/path/to/seg_inference_model --use_camera=1 --use_gpu=1 --use_erode=1 --save_dir=output
  ```

  * 使用加密后的模型对单张图片做预测
F
FlyingQianMM 已提交
243

F
FlyingQianMM 已提交
244
  如果未对模型进行加密,请参考[加密PaddleX模型](https://github.com/PaddlePaddle/PaddleX/blob/develop/docs/tutorials/deploy/deploy_server/encryption.html#paddlex)对模型进行加密。例如加密后的检测模型所在目录为`/path/to/encrypted_det_inference_model`,密钥为`yEBLDiBOdlj+5EsNNrABhfDuQGkdcreYcHcncqwdbx0=`;加密后的分割模型所在目录为`/path/to/encrypted_seg_inference_model`,密钥为`DbVS64I9pFRo5XmQ8MNV2kSGsfEr4FKA6OH9OUhRrsY=`
F
FlyingQianMM 已提交
245

F
FlyingQianMM 已提交
246 247 248 249
  ```shell
  ./build/meter/meter --det_model_dir=/path/to/encrypted_det_inference_model --seg_model_dir=/path/to/encrypted_seg_inference_model --image=/path/to/test.jpg --use_gpu=1 --use_erode=1 --save_dir=output --det_key yEBLDiBOdlj+5EsNNrABhfDuQGkdcreYcHcncqwdbx0= --seg_key DbVS64I9pFRo5XmQ8MNV2kSGsfEr4FKA6OH9OUhRrsY=
  ```

F
FlyingQianMM 已提交
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275

## <h2 id="5">模型训练</h2>


#### 前置依赖

* Paddle paddle >= 1.8.0
* Python >= 3.5
* PaddleX >= 1.0.0

安装的相关问题参考[PaddleX安装](https://paddlex.readthedocs.io/zh_CN/latest/install.html)

#### 训练

* 表盘检测的训练
```
python3 /path/to/PaddleX/examples/meter_reader/train_detection.py
```
* 指针和刻度分割的训练

```
python3 /path/to/PaddleX/examples/meter_reader/train_segmentation.py

```

运行以上脚本可以训练本案例的检测模型和分割模型。如果不需要本案例的数据和模型参数,可更换数据,选择合适的模型并调整训练参数。