Skip to content

Commit 3aa4463

Browse files
xmxoxo何熙
and
何熙
authored
update rapidocr_api (#242)
Co-authored-by: 何熙 <[email protected]>
1 parent 4ab68d6 commit 3aa4463

File tree

4 files changed

+134
-21
lines changed

4 files changed

+134
-21
lines changed

api/Dockerfile

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM python:3.10.11-slim-buster
2+
3+
ENV DEBIAN_FRONTEND=noninteractive
4+
5+
# 设置工作目录
6+
WORKDIR /app
7+
8+
RUN pip install --no-cache-dir rapidocr_api -i https://mirrors.aliyun.com/pypi/simple
9+
10+
RUN pip uninstall -y opencv-python && \
11+
pip install --no-cache-dir opencv-python-headless -i https://mirrors.aliyun.com/pypi/simple
12+
13+
EXPOSE 9003
14+
15+
# 升级后可用
16+
# CMD ["bash", "-c", "rapidocr_api -ip 0.0.0.0 -p 9003 -workers 2"]
17+
CMD ["rapidocr_api"]
18+

api/README.md

+53
Original file line numberDiff line numberDiff line change
@@ -1 +1,54 @@
11
### See [Documentation](https://rapidai.github.io/RapidOCRDocs/install_usage/rapidocr_api/usage/)
2+
3+
4+
### API 修改说明
5+
6+
* uvicorn启动时,reload参数设置为False,避免反复加载;
7+
* 增加了启动参数: workers,可启动多个实例,以满足多并发需求。
8+
* 可通过环境变量传递模型参数:det_model_path, cls_model_path, rec_model_path;
9+
* 接口中可传入参数,控制是否使用检测、方向分类和识别这三部分的模型;客户端调用见`demo.py`
10+
* 增加了Dockerfile,可自行构建镜像。
11+
12+
启动服务端:
13+
14+
Windows下启动:
15+
16+
```for win shell
17+
set det_model_path=I:\models\图像相关\OCR\RapidOCR\PP-OCRv4\ch_PP-OCRv4_det_server_infer.onnx
18+
set det_model_path=
19+
20+
set rec_model_path=I:\models\图像相关\OCR\RapidOCR\PP-OCRv4\ch_PP-OCRv4_rec_server_infer.onnx
21+
rapidocr_api
22+
```
23+
24+
Linux下启动:
25+
```shell
26+
# 默认参数启动
27+
rapidocr_api
28+
29+
# 指定参数:端口与进程数量;
30+
rapidocr_api -ip 0.0.0.0 -p 9005 -workers 2
31+
32+
# 指定模型
33+
expert det_model_path=/mnt/sda1/models/PP-OCRv4/ch_PP-OCRv4_det_server_infer.onnx
34+
expert rec_model_path=/mnt/sda1/models/PP-OCRv4/ch_PP-OCRv4_rec_server_infer.onnx
35+
rapidocr_api -ip 0.0.0.0 -p 9005 -workers 2
36+
```
37+
38+
39+
客户端调用说明:
40+
```
41+
cd api
42+
python demo.py
43+
```
44+
45+
构建镜像:
46+
```
47+
cd api
48+
sudo docker build -t="rapidocr_api:0.1.1" .
49+
```
50+
启动镜像:
51+
52+
```
53+
docker run -p 9003:9003 --name rapidocr_api1 --restart always -d rapidocr_api:0.1.1
54+
```

api/demo.py

+34-2
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,49 @@
1313

1414
# print(response.text)
1515

16+
import time
1617
import base64
17-
1818
import requests
1919

2020
url = "http://localhost:9003/ocr"
2121
img_path = "../python/tests/test_files/ch_en_num.jpg"
2222

23+
# 方式一:使用base64编码传
24+
stime = time.time()
2325
with open(img_path, "rb") as fa:
2426
img_str = base64.b64encode(fa.read())
2527

2628
payload = {"image_data": img_str}
27-
response = requests.post(url, data=payload, timeout=60)
29+
response = requests.post(url, data=payload) #, timeout=60
2830

2931
print(response.json())
32+
etime = time.time() - stime
33+
print(f'用时:{etime:.3f}秒')
34+
35+
print('-'*40)
36+
37+
# 方式二:使用文件上传方式
38+
stime = time.time()
39+
with open(img_path, 'rb') as f:
40+
file_dict = {'image_file': (img_path, f, 'image/png')}
41+
response = requests.post(url, files=file_dict) #, timeout=60
42+
print(response.json())
43+
44+
etime = time.time() - stime
45+
print(f'用时:{etime:.3f}秒')
46+
print('-'*40)
47+
48+
# 方式三:控制是否使用检测、方向分类和识别这三部分的模型; 不使用检测模型:use_det=False
49+
stime = time.time()
50+
img_path = "../python/tests/test_files/test_without_det.jpg"
51+
52+
with open(img_path, 'rb') as f:
53+
file_dict = {'image_file': (img_path, f, 'image/png')}
54+
# 添加控制参数
55+
data = {"use_det":False, "use_cls":True, "use_rec":True}
56+
response = requests.post(url, files=file_dict, data=data) #, timeout=60
57+
print(response.json())
58+
59+
etime = time.time() - stime
60+
print(f'用时:{etime:.3f}秒')
61+
print('-'*40)

api/rapidocr_api/main.py

+29-19
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# -*- encoding: utf-8 -*-
22
# @Author: SWHL
33
# @Contact: [email protected]
4+
45
import argparse
56
import base64
67
import io
8+
import os
79
import sys
810
from pathlib import Path
911
from typing import Dict
@@ -19,37 +21,47 @@
1921

2022
class OCRAPIUtils:
2123
def __init__(self) -> None:
22-
self.ocr = RapidOCR()
24+
# 从环境变量中读取参数
25+
det_model_path = os.getenv("det_model_path", None)
26+
cls_model_path = os.getenv("cls_model_path", None)
27+
rec_model_path = os.getenv("rec_model_path", None)
28+
29+
self.ocr = RapidOCR(det_model_path=det_model_path, cls_model_path=cls_model_path, rec_model_path=rec_model_path)
2330

24-
def __call__(self, img: Image.Image) -> Dict:
31+
def __call__(self, img: Image.Image, use_det=None, use_cls=None, use_rec=None) -> Dict:
2532
img = np.array(img)
26-
ocr_res, _ = self.ocr(img)
33+
ocr_res, _ = self.ocr(img, use_det=use_det, use_cls=use_cls, use_rec=use_rec)
2734

2835
if not ocr_res:
2936
return {}
3037

31-
out_dict = {
32-
str(i): {
33-
"rec_txt": rec,
34-
"dt_boxes": dt_box,
35-
"score": f"{score:.4f}",
36-
}
37-
for i, (dt_box, rec, score) in enumerate(ocr_res)
38-
}
38+
# 转换为字典格式: 兼容所有参数情况
39+
out_dict = {}
40+
for i, dats in enumerate(ocr_res):
41+
values = {}
42+
for dat in dats:
43+
if type(dat) == str:
44+
values["rec_txt"] = dat
45+
if type(dat) == np.float64:
46+
values["score"] = f"{dat:.4f}"
47+
if type(dat) == list:
48+
values["dt_boxes"] = dat
49+
out_dict[str(i)] = values
50+
3951
return out_dict
4052

4153

4254
app = FastAPI()
4355
processor = OCRAPIUtils()
4456

45-
4657
@app.get("/")
4758
async def root():
4859
return {"message": "Welcome to RapidOCR API Server!"}
4960

50-
5161
@app.post("/ocr")
52-
async def ocr(image_file: UploadFile = None, image_data: str = Form(None)):
62+
async def ocr(image_file: UploadFile = None, image_data: str = Form(None),
63+
use_det: bool = Form(None), use_cls: bool = Form(None), use_rec: bool = Form(None)):
64+
5365
if image_file:
5466
img = Image.open(image_file.file)
5567
elif image_data:
@@ -60,19 +72,17 @@ async def ocr(image_file: UploadFile = None, image_data: str = Form(None)):
6072
raise ValueError(
6173
"When sending a post request, data or files must have a value."
6274
)
63-
64-
ocr_res = processor(img)
75+
ocr_res = processor(img, use_det=use_det, use_cls=use_cls, use_rec=use_rec)
6576
return ocr_res
6677

67-
6878
def main():
6979
parser = argparse.ArgumentParser("rapidocr_api")
7080
parser.add_argument("-ip", "--ip", type=str, default="0.0.0.0", help="IP Address")
7181
parser.add_argument("-p", "--port", type=int, default=9003, help="IP port")
82+
parser.add_argument('-workers', "--workers", type=int, default=1, help='number of worker process')
7283
args = parser.parse_args()
7384

74-
uvicorn.run("rapidocr_api.main:app", host=args.ip, port=args.port, reload=True)
75-
85+
uvicorn.run("rapidocr_api.main:app", host=args.ip, port=args.port, reload=0, workers=args.workers)
7686

7787
if __name__ == "__main__":
7888
main()

0 commit comments

Comments
 (0)