README.md 11.1 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
# 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
L
LKKlein 已提交
30
echo "export PATH=$PATH:$GOROOT/bin" >> ~/.bashrc
L
LKKlein 已提交
31 32
# 配置GOPATH,即go相关package的安装目录,可自定义一个目录
echo "export GOPATH=$HOME/golang" >> ~/.bashrc
L
LKKlein 已提交
33
echo "export PATH=$PATH:$GOPATH/bin" >> ~/.bashrc
L
LKKlein 已提交
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
# 配置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
L
LKKlein 已提交
155
export PADDLE_INFER=`$HOME/paddle_inference`
L
LKKlein 已提交
156 157

# 执行编译
L
LKKlein 已提交
158
export PADDLE_ROOT=`pwd`
L
LKKlein 已提交
159 160
mkdir build
cd build
L
LKKlein 已提交
161
cmake -DFLUID_INFERENCE_INSTALL_DIR=$PADDLE_INFER \
L
LKKlein 已提交
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
      -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
```

L
LKKlein 已提交
184
其中`paddle`就是Paddle库的C语言预测API,`version.txt`中包含当前预测库的版本信息。最后,将C推理库配置到环境变量。
L
LKKlein 已提交
185

L
LKKlein 已提交
186 187 188 189 190 191
```shell
echo "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PADDLE_ROOT/build/fluid_inference_c_install_dir/paddle/lib" >> ~/.bashrc
echo "export LIBRARY_PATH=$LIBRARY_PATH:$PADDLE_ROOT/build/fluid_inference_c_install_dir/paddle/lib" >> ~/.bashrc

souce ~/.bashrc
```
L
LKKlein 已提交
192 193 194 195 196

## 2. paddleocr-go预测库

### 2.1 安装paddleocr-go

L
LKKlein 已提交
197
确保C推理库已配置到环境变量,然后直接执行安装命令
L
LKKlein 已提交
198 199

```shell
L
LKKlein 已提交
200
go get -u github.com/PaddlePaddle/PaddleOCR/thirdparty/paddleocr-go
L
LKKlein 已提交
201 202 203 204 205 206 207
```

### 2.2 相关使用API

在go中使用import引入包

```go
L
LKKlein 已提交
208
import github.com/PaddlePaddle/PaddleOCR/thirdparty/paddleocr-go/ocr
L
LKKlein 已提交
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
```

- 预测结果结构体

```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

L
LKKlein 已提交
262
### 3.1 生成预测demo
L
LKKlein 已提交
263

L
LKKlein 已提交
264
以下两种方式均可生成预测demo文件,任选其一即可
L
LKKlein 已提交
265

L
LKKlein 已提交
266
- 通过下载`paddleocr-go`代码并编译
L
LKKlein 已提交
267 268 269

```shell
git clone https://github.com/PaddlePaddle/PaddleOCR
L
LKKlein 已提交
270 271 272 273
cd PaddleOCR/thirdparty/paddleocr-go

# 确保C动态库路径已在环境变量中,执行以下命令生成ppocr-go文件
go build ppocr-go.go
L
LKKlein 已提交
274 275
```

L
LKKlein 已提交
276
- 通过go package自动安装
L
LKKlein 已提交
277 278

```shell
L
LKKlein 已提交
279 280
# 执行后会自动在$GOPATH/bin下生成ppocr-go文件,如果配置了PATH=$PATH:$GOPATH/bin,以下预测命令可以去掉`./`,直接执行ppocr-go
go get -u github.com/PaddlePaddle/PaddleOCR/thirdparty/paddleocr-go
L
LKKlein 已提交
281 282
```

L
LKKlein 已提交
283 284 285 286 287 288
### 3.2 修改预测配置

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

比如,将`use_gpu`改为`false`,使用CPU执行预测;将`det_model_dir`, `rec_model_dir`, `cls_model_dir`都更改为自己的本地模型路径,也或者是更改字典`rec_char_dict_path`的路径,这四个路径如果配置http链接,会自动下载到本地目录。另外,配置参数包含了预测引擎、检测模型、检测阈值、方向分类模型、识别模型及阈值的相关参数,具体参数的意义可参见[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)

L
LKKlein 已提交
289 290 291 292 293 294 295
### 3.3 执行预测demo

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

#### 3.3.1 单张图预测

```shell
L
LKKlein 已提交
296
./ppocr-go --config config/conf.yaml --image images/test.jpg
L
LKKlein 已提交
297 298 299 300 301 302 303 304 305
```

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

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

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

```shell
L
LKKlein 已提交
306
./ppocr-go --config config/conf.yaml --image_dir ./images
L
LKKlein 已提交
307 308 309 310 311 312 313 314 315
```

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

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

#### 3.3.3 开启OCR Server

```shell
L
LKKlein 已提交
316
./ppocr-go --use_servering --port=18600
L
LKKlein 已提交
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
```

开启服务后,可以在其他客户端中通过`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)