Skip to content

rapidocr_api队列实现代码 #5

@nzm001

Description

@nzm001

问题描述 / Problem Description

之前有说当前rapidocr_api的worker参数并没有实际作用。

运行环境 / Runtime Environment

  • Ubuntu 24.04
  • Python 3.12.3

实现代码 / Code

服务端

from flask import Flask, request, jsonify
import base64
from queue import Queue
from rapidocr_onnxruntime import RapidOCR
import sys
import logging

# 配置日志格式
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

app = Flask(__name__)

# 初始化OCR引擎池
def init_engine_pool(pool_size):
    engine_queue = Queue(maxsize=pool_size)
    for _ in range(pool_size):
        engine = RapidOCR()
        engine_queue.put(engine)
    return engine_queue

# 命令行参数处理
if len(sys.argv) != 2:
    print("Usage: python ocr_server.py N")
    sys.exit(1)

try:
    POOL_SIZE = int(sys.argv[1])
except ValueError:
    print("Error: N must be an integer")
    sys.exit(1)

engine_pool = init_engine_pool(POOL_SIZE)

@app.route('/ocr', methods=['POST'])
def ocr_service():
    # 参数校验
    if 'image' not in request.json:
        return jsonify({"error": "Missing image parameter"}), 400
    
    # Base64解码
    try:
        img_b64 = request.json['image'].split(',')[-1]
        img_bytes = base64.b64decode(img_b64)
    except Exception as e:
        logging.error(f"Base64解码失败: {str(e)}")
        return jsonify({"error": f"无效的图片数据: {str(e)}"}), 400

    # 获取OCR引擎
    engine = engine_pool.get()
    try:
        # 直接处理二进制数据
        result, elapse = engine(img_bytes)
    except Exception as e:
        logging.error(f"OCR处理失败: {str(e)}")
        return jsonify({"error": f"OCR处理失败: {str(e)}"}), 500
    finally:
        engine_pool.put(engine)

    # 结果格式化(根据实际数据结构调整)
    formatted = []
    for item in result:
        formatted.append({
            "coordinates": item[0],  # 保持原始坐标结构
            "text": item[1],
            "confidence": float(item[2])
        })

    return jsonify({
        "result": formatted,
        "processing_time": elapse,
        "engine_count": POOL_SIZE
    })

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9003, threaded=True)

服务端运行(启动5个实例)

python ocr_server.py 5

客户端

import requests
import base64
import time

def test_ocr(image_path, url='http://localhost:9003/ocr'):
    with open(image_path, 'rb') as f:
        img_b64 = base64.b64encode(f.read()).decode()
    
    start = time.time()
    response = requests.post(url, json={'image': img_b64})
    latency = time.time() - start
    
    if response.status_code == 200:
        print(f"识别成功 | 耗时: {latency:.2f}s")
        return response.json()
    else:
        print(f"识别失败 | 状态码: {response.status_code}")
        return response.text

# 并发测试示例
from concurrent.futures import ThreadPoolExecutor

with ThreadPoolExecutor(max_workers=5) as executor:
    futures = [executor.submit(test_ocr, 'test.jpg') for _ in range(10)]
    results = [f.result() for f in futures]

问题说明

  1. api返回结果和runtime返回结果统一,现在api也可以返回处理时间、置信度。可以查看服务器的三个processing_time用来优化运行了。
{'engine_count': 4,
 'processing_time': [3.3301830849995895,
  0.4641904830932617,
  22.541740894317627],
 'result': [{'confidence': 0.9690895353044783,
   'coordinates': [[95.0, 16.0], [502.0, 16.0], [502.0, 35.0], [95.0, 35.0]],
   'text': '广州软件院开箱测评12款开源OCR,Rapid0CR表现优异→link'},
  {'confidence': 0.5223508477210999,
   'coordinates': [[1264.0, 17.0],
    [1283.0, 17.0],
    [1283.0, 35.0],
    [1264.0, 35.0]],
   'text': '×'},
...
  1. 运行openvino时,警告,应该是要修改utils/infer_engine.py里的openvino.runtime
<frozen importlib.util>:208: DeprecationWarning: The `openvino.runtime` module is deprecated and will be removed in the 2026.0 release. Please replace `openvino.runtime` with `openvino`.
  1. 这不是一个bug但须要申明:在一个例如6核12线程的CPU上跑,开6个实例,同时识别6张图片,RapidOCR()要比RapidOCR(intra_op_num_threads=1)慢一倍,完美的互相拖后腿。(inter_op_num_threads不知道啥用,我测试对CPU的影响在误差范围内,难道是双CPU才有影响)
  2. 猜测是openvino的问题:在测试openvino时,不论用这里的代码,还是同时运行多个rapidocr_api(openvino版),开5个实例,都只用了一核或者说一半的核心。测试CPU为2核心4线程,在htop中查看,0123核心只有23使用率100%,01都只用了10-15%。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions