README.md 10.2 KB
Newer Older
L
LKKlein 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 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 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
# PaddleOCR-GO

本服务是[PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)的golang部署版本。

## 1. 环境准备

### 运行环境

- go: 1.14
- OpenCV: 4.3.0
- PaddlePaddle: 1.8.4
- 编译环境:cmake 3.15.4   |   gcc 4.8.5
- 基于Centos 7.4运行环境编译,Windows请自行解决`OpenCV``PaddlePaddle`的编译问题

*另外,以下编译以`.bashrc`个人环境变量配置文件,如果使用`zsh`,请自行更换为`.zshrc`*

### 1.1 安装golang

从官网下载[golang](https://golang.org/dl/),建议选择1.13版本以上进行安装。下载完成后,直接解压你需要的安装目录,并配置相关环境变量,此处以1.14版本为例。

```shell
# 下载golang
wget https://golang.org/dl/go1.14.10.linux-amd64.tar.gz

# 解压到 /usr/local 目录下
tar -xzvf go1.14.10.linux-amd64.tar.gz -C /usr/local

# 配置GOROOT,即go的安装目录
echo "export GOROOT=/usr/local/go" >> ~/.bashrc
# 配置GOPATH,即go相关package的安装目录,可自定义一个目录
echo "export GOPATH=$HOME/golang" >> ~/.bashrc
# 配置GOPROXY,即go mod包管理器的下载代理,同时打开mod模式
echo "export GO111MODULE=on" >> ~/.bashrc
echo "export GOPROXY=https://mirrors.aliyun.com/goproxy/" >> ~/.bashrc
source ~/.bashrc
```

### 1.2 编译OpenCV库

go语言中,OpenCV的使用主要以[gocv](https://github.com/hybridgroup/gocv)包为主,gocv使用cgo调用OpenCV提供接口,因此还是需要编译OpenCV库。  

**踩坑指南之一:[gocv官方实现](https://github.com/hybridgroup/gocv)中,部分接口并没有与原版C++的OpenCV的API保持一致,导致图片处理结果会出现一定的数值偏差。为处理这种偏差,[该仓库](https://github.com/LKKlein/gocv)fork了一份gocv官方源码,并对部分这些不一致的API进行了修正,保证结果与其他语言的一致性。**

对于OpenCV的编译,gocv官方提供了[Makefile](https://github.com/LKKlein/gocv/blob/lk/Makefile),可以一键进行安装,具体安装步骤详见[官方指南](https://github.com/LKKlein/gocv/blob/lk/README_ORIGIN.md#ubuntulinux)

这里提供逐步安装的方式,方便排查错误。

- 下载并解压OpenCV-4.3.0和OpenCV-Contrib-4.3.0

```shell
# 创建opencv安装目录
mkdir -p ~/opencv

# 下载OpenCV
cd ~/opencv
curl -sL https://github.com/opencv/opencv/archive/4.3.0.zip > opencv.zip
unzip -q opencv.zip
rm -rf opencv.zip

# 下载OpenCV-Contrib
curl -sL https://github.com/opencv/opencv_contrib/archive/4.3.0.zip > opencv-contrib.zip
unzip -q opencv-contrib.zip
rm -rf opencv-contrib.zip
```

- 安装相关依赖

```shell
sudo yum -y install pkgconfig cmake git gtk2-devel libpng-devel libjpeg-devel libtiff-devel tbb tbb-devel libdc1394-devel
```

- 编译安装

```shell
mkdir -p ~/.local/opencv-4.3.0
cd ~/opencv/opencv-4.3.0
mkdir build
cd build
cmake -D WITH_IPP=OFF \
      -D WITH_OPENGL=OFF \
      -D WITH_QT=OFF \
      -D BUILD_EXAMPLES=OFF \
      -D BUILD_TESTS=OFF \
      -D BUILD_PERF_TESTS=OFF  \
      -D BUILD_opencv_java=OFF \
      -D BUILD_opencv_python=OFF \
      -D BUILD_opencv_python2=OFF \
      -D BUILD_opencv_python3=OFF \
      -D OPENCV_GENERATE_PKGCONFIG=ON \
      -D CMAKE_INSTALL_PREFIX=$HOME/.local/opencv-4.3.0 \
      -D OPENCV_ENABLE_NONFREE=ON \
      -D OPENCV_EXTRA_MODULES_PATH=$HOME/opencv/opencv_contrib-4.3.0/modules ..
make -j8
make install
sudo ldconfig
```

make进行编译时,可能出现因`xfeatures2d`的两个模块下载失败导致的编译失败,这里只需要手动下载这部分文件到`$HOME/opencv/opencv_contrib-4.3.0/modules/xfeatures2d/src`目录下,然后重新执行`make -j8`即可。这部分文件地址可参考[这里](https://github.com/opencv/opencv_contrib/issues/1301#issuecomment-447181426)给出的链接。

- 配置环境变量

```shell
echo "export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$HOME/.local/opencv-4.3.0/lib64/pkgconfig" >> ~/.bashrc
echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/.local/opencv-4.3.0/lib64" >> ~/.bashrc
source ~/.bashrc
```

- 验证安装

```shell
# 安装gocv包,先mod init
go mod init opencv
go get -u github.com/LKKlein/gocv

# 验证安装结果
cd $GOPATH/pkg/mod/github.com/!l!k!klein/gocv@v0.28.0
go run ./cmd/version/main.go

# 输出
# gocv version: 0.28.0
# opencv lib version: 4.3.0
```

### 1.3 编译PaddlePaddle的C语言API

go语言只能通过cgo调用C语言API,而不能直接与C++进行交互,因此需要编译PaddlePaddle的C语言API。当然,也可以自己写C语言调用C++的代码和头文件,这样就可以直接使用PaddlePaddle提供的已编译的C++推理库,无需自己手动编译,详见[该仓库](https://github.com/LKKlein/paddleocr-go/tree/dev_cxx)

- 获取PaddlePaddle源代码

```shell
cd ~
git clone --recurse-submodules https://github.com/paddlepaddle/paddle

# 切换到v1.8.4版本
cd paddle
git checkout v1.8.4

# 目前版本无论单卡还是多卡都需要先安装nccl
git clone https://github.com/NVIDIA/nccl.git
make -j8
make install
```

- 编译Paddle源代码

**踩坑指南之二:PaddlePaddle的C语言API实现有一个bug,即获取输入输出变量名时只能获取到第一个模型的变量名,后续模型都无法获取输入输出变量名,进而无法获取到模型输出,详情见[issue](https://github.com/PaddlePaddle/Paddle/issues/28309)。因此,编译前需要手动将`paddle/fluid/inference/capi/pd_predictor.cc`文件中`210行`与`215行`的`static`删除。**

在处理完该bug之后,才能进行后续编译。相关编译参数见[官方文档](https://www.paddlepaddle.org.cn/documentation/docs/zh/advanced_guide/inference_deployment/inference/build_and_install_lib_cn.html#id12),注意部分参数需要相关依赖,请确保依赖完整再启用。

```shell
# 创建c++推理库文件夹
mkdir -p ~/paddle_inference
export PADDLE_ROOT=`$HOME/paddle_inference`

# 执行编译
mkdir build
cd build
cmake -DFLUID_INFERENCE_INSTALL_DIR=$PADDLE_ROOT \
      -DWITH_CONTRIB=OFF \
      -DCMAKE_BUILD_TYPE=Release \
      -DWITH_PYTHON=OFF \
      -DWITH_MKL=ON \
      -DWITH_GPU=ON \
      -DON_INFER=ON \
      --WITH_MKLDNN=ON \
      --WITH_XBYAK=ON \
      --WITH_DSO=OFF ..
make
make inference_lib_dist
```

编译完成后,可以在`build/fluid_inference_c_install_dir`目录下,看到以下生成的文件

```
build/fluid_inference_c_install_dir
├── paddle
├── third_party
└── version.txt
```

其中`paddle`就是Paddle库的C语言预测API,`version.txt`中包含当前预测库的版本信息。


## 2. paddleocr-go预测库

### 2.1 安装paddleocr-go

直接执行安装命令

```shell
go get github.com/PaddlePaddle/PaddleOCR/deploy/paddleocr-go
```

### 2.2 相关使用API

在go中使用import引入包

```go
import github.com/PaddlePaddle/PaddleOCR/deploy/paddleocr-go/ocr
```

- 预测结果结构体

```go
type OCRText struct {
	BBox  [][]int `json:"bbox"`
	Text  string  `json:"text"`
	Score float64 `json:"score"`
}
```

一张图的OCR结果包含多个`OCRText`结果,每个结果包含预测框、预测文本、预测文本得分。

- OCR预测类


```go
func NewOCRSystem(confFile string, a map[string]interface{}) *OCRSystem
```

`OCRSystem`是主要对外提供API的结构;

`confFile`是yaml配置文件的路径,可在配置文件中修改相关预测参数,也可以传空字符串,这时会全部使用默认配置;

`a`是可以在代码中直接定义的配置参数,优先级高于配置文件,会覆盖配置文件和默认配置的参数。

- 单张图预测API

```go 
func (ocr *OCRSystem) PredictOneImage(img gocv.Mat) []OCRText
```


- 图片文件夹预测API

```go
func (ocr *OCRSystem) PredictDirImages(dirname string) map[string][]OCRText
```

`dirname`图片文件夹的目录,默认会预测改目录下所有`jpg``png`图片,并返回每张图的预测结果。

- OCR Server

```go
func (ocr *OCRSystem) StartServer(port string)
```

开启OCR预测Server,开启后,使用`post`请求上传需要识别的图片至`http://$ip:$port/ocr`即可直接获取该图片上所有文本的识别结果。其中,`$ip`是开启服务的主机`ip``127.0.0.1`的本地ip, `$port`是传入的端口参数。


## 3. 预测demo

### 3.1 修改预测配置

当前给定的配置文件`config/conf.yaml`中,包含了默认的OCR预测配置参数,可根据个人需要更改相关参数。

比如,将`use_gpu`改为`false`,使用CPU执行预测;将`det_model_dir`, `rec_model_dir`, `cls_model_dir`都更改为自己的本地模型路径,也或者是更改字典`rec_char_dict_path`的路径。配置参数包含了预测引擎、检测模型、检测阈值、方向分类模型、识别模型及阈值的相关参数,具体参数的意义可参见[PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_ch/whl.md#%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E)

### 3.2 编译预测demo

- 下载`paddleocr-go`代码

```shell
git clone https://github.com/PaddlePaddle/PaddleOCR
cd PaddleOCR/deploy/paddleocr-go
```

- 准备paddle_c环境

```shell
cp -r ~/paddle/build/fluid_inference_c_install_dir/* paddle_c/
```

- 编译demo

```shell
go build demo.go
```

### 3.3 执行预测demo

预测demo提供了三种预测方式,分别是单张图预测、文件夹批量预测、OCR Server预测。三者命令行优先级依次降低。

#### 3.3.1 单张图预测

```shell
./demo --config config/conf.yaml --image images/test.jpg
```

执行完成,会输出以下内容:

<img src="./images/result/single_img_result.jpg" style="zoom:80%;" />

#### 3.3.2 文件夹批量预测

```shell
./demo --config config/conf.yaml --image_dir ./images
```

执行完成,会输出以下内容:

<img src="./images/result/img_dir_result.jpg" style="zoom:80%;" />

#### 3.3.3 开启OCR Server

```shell
./demo --use_servering --port=18600
```

开启服务后,可以在其他客户端中通过`post`请求进行ocr预测。此处以`Python`客户端为例,如下所示

```python
import requests

files = {'image': open('images/test.jpg','rb')}
url = "http://127.0.0.1:18600/ocr"

r = requests.post(url, files=files)
print(r.text)
```

执行完成可以得到以下结果

![](./images/result/python_client_result.jpg)

最后,在Python中将上述结果可视化可以得到以下结果

![](./images/result/python_vis_result.jpg)