ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

RapidOCR本地部署实战:从选型到Ubuntu 22.04上线全流程

RapidOCR本地部署实战:从选型到Ubuntu 22.04上线全流程 大约在去年年中我接了一个内部工具的需求服务器放在内网所有文档图片不能出网需要本地跑一套OCR来识别中文票据、截图和扫描件。第一反应就是用PaddleOCR毕竟识别率摆在那。可真到部署环节才发现PaddlePaddle框架的依赖、版本兼容、运行库这些事比想象中麻烦得多。后来转用RapidOCR识别效果几乎没差别部署却轻松了整整一个量级。这篇文章就把我从选型到部署上线的完整过程写下来从技术原理到Ubuntu 22.04上的实际操作再顺带排查几个高频问题给正在折腾OCR本地化的朋友一份能直接照着做的参考。1. OCR选型为什么最后留下RapidOCR1.1 先说说PaddleOCR的硬伤PaddleOCR的识别率确实强这一点我不否认。但如果你把它部署到生产环境尤其是离线环境就会遇到一连串跟模型识别率完全无关的麻烦。第一是PaddlePaddle框架本身的依赖问题。在Windows上部署需要VC运行库很多人想在VS2017环境下编译或运行PaddleOCR光环境配置就能折腾一整天各种DLL缺失、版本冲突一个接一个。在Linux上paddlepaddle的so库跟系统自带的OpenCV、protobuf经常发生版本冲突轻则警告刷屏重则直接段错误排查起来很费时间。第二是模型和框架的开销。PaddleOCR完整推理要加载PaddlePaddle动态图内存占用高启动也慢。我试过在一台2核4G的机器上单机部署光模型加载阶段就能吃掉接近1GB内存并发请求一旦上来内存立刻吃紧。如果服务器还要跑其他服务这种资源占用很不划算。第三是Python版本兼容策略。PaddlePaddle的版本要求一直在变生产环境如果正好卡在不被支持的Python版本上pip install就会提示找不到匹配的whl包。你只能在升级Python和降低PaddlePaddle版本之间二选一而这两个选择都会带来额外的连锁问题。1.2 再看Tesseract的准确率Tesseract是老牌开源OCR名气和社区影响力都很大至今仍有很多人在搜索“tesseract ocr怎么运行”。但它在中文场景下的表现确实一般。我拿一份中文账单截图做过对比Tesseract的整行准确率不到80%大量汉字被识别成相似字形数字偶尔还会串行标点符号基本靠运气。如果你要识别的是印刷体英文文档或者字体规范、背景干净的单行文本Tesseract还能一战。可一旦涉及中文、手写、倾斜文本或者复杂版面它很难达到生产可用标准。这也是我在实际项目中彻底放弃它的原因——OCR的绝大部分业务场景恰恰是中文内容。1.3 RapidOCR的优势模型开源推理轻量RapidOCR的思路非常聪明模型直接复用PaddleOCR训练好的模型只把格式导出成ONNX然后通过微软的ONNX Runtime做推理。这一步就同时解决了两大痛点不需要安装PaddlePaddle这个重型框架也不需要额外处理VC运行库、系统原生依赖这些东西。部署复杂度一下子从“搭好一个框架”降到了“pip安装一个Python包”。因为推理走的是ONNX Runtime计算图经过专门优化在没有GPU的机器上CPU推理速度通常比直接跑PaddlePaddle更快内存占用也更小。这一点在服务器环境里非常实用。我当时最看重的还有一点模型是开放的、可替换的。RapidOCR支持你灵活替换det、cls、rec三个模型如果手头有自己训练或者微调过的模型导出成ONNX格式后可以无缝接上。这对后面对接特定业务场景、优化识别效果很有帮助。为了让你更直观地理解三者的差别我把自己在实际选型时做的对比整理成了一张表对比项PaddleOCRTesseractRapidOCR中文识别率高中低高与PaddleOCR同源部署依赖PaddlePaddle全套框架系统级运行库与训练数据仅需onnxruntime模型体积较大较小中等CPU推理性能一般一般较好跨平台能力受框架限制较多较好好模型可替换性一般一般好2. RapidOCR的技术原理这些概念不搞懂后面全靠猜2.1 ONNX Runtime到底是什么很多人搜索“微软的onnx和rapidocr”其实就是想搞清楚RapidOCR和ONNX Runtime之间的关系。ONNX Runtime是微软开源的一个跨平台推理引擎专门用来加载和执行ONNX格式的模型。ONNX本身是一种开放的模型交换格式你可以把PyTorch、PaddlePaddle、TensorFlow等不同框架训练好的模型统一导出成ONNX再用ONNX Runtime加载推理。RapidOCR利用的就是这个能力PaddleOCR训练出来的模型先被冻结并导出成ONNX推理阶段完全交给ONNX Runtime。这样做的好处是RapidOCR本身不再依赖PaddlePaddle自然绕开了PaddlePaddle在部署时的一系列生态问题。换个角度理解RapidOCR就像一个把PaddleOCR模型的威力封装成了轻量接口的工具。底层推理引擎帮你处理了硬件适配、算子优化、线程调度这些复杂问题你在上层只需要关心输入图片和输出文本即可。这套思路还带来了一个附加收益只要ONNX Runtime能跑的平台RapidOCR几乎都能跑。Windows、Linux、macOS、ARM设备都没问题。我们在Ubuntu 22.04上部署本质上就是给ONNX Runtime准备一个干净的Python环境而已。各类国产Linux发行版上只要Python环境能装onnxruntimeRapidOCR同样能跑。2.2 检测、方向分类、识别三步走RapidOCR的核心流程分三步。第一步是文本检测对应det模型。模型使用DBDifferentiable Binarization可微二值化算法找出图片里所有可能包含文字的区域输出一串多边形框坐标。这一步至关重要如果文本区域没有被检测出来后面识别环节再准也没有意义。我遇到的很多“no text detected”问题根源都在这一步。第二步是方向分类对应cls模型。检测到的文本区域可能需要旋转矫正尤其是扫描件和手机拍的照片很可能存在180度倒置的情况。方向分类器判断每个文本区域是0度还是180度然后自动矫正避免下一步识别时拿到倒着的文字。第三步是文本识别对应rec模型。把每个矫正后的文本区域裁剪出来送进CRNN类的识别模型通过CTC解码输出最终字符串。这三个模型各司其职缺一不可。我在排查识别问题时有个习惯先看检测框画出来是否准确再看方向是否正常最后才怀疑识别模型。按照这个顺序排查大多数问题都能快速定位。2.3 模型文件与关键参数解读安装rapidocr_onnxruntime之后默认模型就放在安装包内部一般在site-packages/rapidocr_onnxruntime/models目录下。模型包含三个文件命名分别带有det、cls、rec标识。部分版本还会附带字典文件因为中文识别需要把模型的输出按字典映射成对应的汉字。关键参数方面平时调得最多的就是检测阈值。det_thresh控制“一个像素算不算文本”的分数门限det_box_thresh控制“一个候选框算不算最终文本框”的门限。这两个值和识别速度有直接关系阈值越低候选框越多需要后续处理的区域越多耗时自然越长。方向分类器的开关参数use_cls用来控制是否启用方向矫正。这里我需要特别提醒不同版本RapidOCR的API有过调整。早期版本直接传det_thresh这种参数名新版本可能包装成了params字典参数路径可能变成“Det.thresh”“Det.box_thresh”。所以拿到某个版本之后先运行help(RapidOCR())查看当前支持的参数签名不要照抄老博客里的命令否则很容易报参数错误。我还习惯记录一个参数速查表方便在不同项目里快速复现参数作用调整建议Det.thresh文本检测分数阈值文字颜色浅、背景干扰多时适当调低Det.box_thresh候选框过滤阈值检测框不全、压到文字时调低use_cls是否启用方向分类图片全部正向时可关闭提速默认建议开启3. Ubuntu 22.04本地部署实操从零到Web服务3.1 环境准备创建干净的Python虚拟环境我用的机器是Ubuntu 22.04系统自带Python 3.10这个版本正好在ONNX Runtime的支持范围内。为了不污染系统环境我习惯先建一个独立的虚拟环境。sudo apt update sudo apt install -y python3-venv python3-pip mkdir -p ~/rapidocr-web cd ~/rapidocr-web python3 -m venv venv source venv/bin/activate激活虚拟环境之后先把pip升级到最新版本这一步可以避免后续安装依赖时出现解析问题pip install --upgrade pip这里有个小经验如果系统Python是3.8以下的旧版本建议先升级Python再继续否则pip在解析onnxruntime的依赖时很可能提示找不到匹配版本后面装RapidOCR也会很痛苦。Ubuntu 22.04自带的Python 3.10不需要担心这个问题。3.2 安装RapidOCR并跑通第一张图片在虚拟环境中直接安装pip install rapidocr_onnxruntime装完之后先别急着写业务代码拿一张测试图片跑一下确认环境完全正常python -c from rapidocr_onnxruntime import RapidOCR; engine RapidOCR(); result, elapse engine(test.png); print(result)新版API返回的是一个元组第一个元素是识别结果列表第二个是耗时字典。每个识别结果项一般长这样[box, text, score]box是四个角点坐标text是识别出的文本score是置信度。我用的是一张带中文的白底截图测试输出结果一次就出来了每一行的文字和坐标都清清楚楚CPU推理耗时大约几百毫秒。到这里核心OCR能力已经通了。3.3 用FastAPI把OCR封装成Web接口命令行能跑只是第一步实际项目里我要把它做成一个可以被其他系统调用的HTTP服务。FastAPI加Uvicorn是我最常用的组合代码量少性能也好。先安装依赖pip install fastapi uvicorn python-multipart然后写一个简单的后端服务# app.py import os import numpy as np import cv2 from fastapi import FastAPI, UploadFile, File from rapidocr_onnxruntime import RapidOCR app FastAPI() engine RapidOCR() app.post(/ocr) async def ocr(file: UploadFile File(...)): data await file.read() img cv2.imdecode(np.frombuffer(data, np.uint8), cv2.IMREAD_COLOR) if img is None: return {code: 1, msg: image decode failed} result, elapse engine(img) if not result: return {code: 0, data: []} items [] for box, text, score in result: items.append({ box: box.tolist() if hasattr(box, tolist) else box, text: text, score: float(score) }) return {code: 0, data: items} if __name__ __main__: import uvicorn uvicorn.run(app, host0.0.0.0, port8000)这里有个非常关键的细节引擎初始化要放在模块加载时执行只做一次。我最早写的时候把RapidOCR()放在了函数内部结果每个请求都要重新加载模型一次请求要好几秒还经常把内存撑爆。改成全局初始化之后首个请求会有模型加载耗时后续请求就非常稳定。启动服务python app.py然后在另一个终端用curl测试curl -X POST -F filetest.png http://127.0.0.1:8000/ocr返回的JSON里能看到检测框坐标、识别文本和置信度。到这里一个本地OCR的Web服务就算跑起来了内网其他系统直接POST图片数据就能拿到文字结果。如果不想写前端页面这个接口已经能满足绝大多数自动化需求。3.4 识别效果优化关键参数与实际权衡接口跑通之后我开始在真实图片上测试发现有些票据扫描件的识别率不理想。总结下来主要调整方向有三个。第一是图像预处理。OCR对图片清晰度非常敏感。我常用的手段是在调用RapidOCR之前先做一步缩放让文字高度尽量在30像素以上。如果图片倾斜明显就先做仿射矫正对比度太低就用直方图均衡化增强文字和背景的边界。第二是调整检测阈值。遇到密集文字或者字迹较浅的图片默认阈值可能漏检。在我使用的版本里可以通过params字典传入参数engine RapidOCR(params{ Det.thresh: 0.3, Det.box_thresh: 0.5 })不同版本的参数路径有差异建议先用help(RapidOCR())查看当前支持的关键字再按实际情况调整。第三是方向分类不要轻易关闭。有些部署方案为了省时间把use_cls关掉但手机拍照、票据扫描这类图片经常存在旋转关掉方向分类之后倒置文字全都会被识别成乱码。只要不是对性能极度敏感我建议保留方向分类。4. 常见问题排查实录这些坑我替你踩过了4.1 no text detected明明有字为什么检测不到这是OCR领域最常见的问题搜索热度也一直很高。字面上是“没有检测到文本”但出现这个提示的可能原因其实有好几个。最常见的原因是图片分辨率太低、文字区域太小。检测模型对特别小的文字目标不敏感我遇到过一张整图很小、文字密密麻麻的截图直接丢进RapidOCR就报了no text detected。解决思路是先放大图片把图片按比例缩放让宽度超过1000像素再送进去。另一个常见原因是文字和背景对比度太低比如白底浅灰色文字或者照片里被阴影干扰的文字。检测模型同样可能漏掉这些弱特征区域。可以对图片做灰度化、二值化或者对比度增强让文字轮廓更明显。还有一种可能往往被忽略你传的图片根本不是文档或截图而是商品照片、风景照这类没有清晰文本区域的图片检测模型输出为空是正常现象。这不属于bug是场景不匹配。排查这类问题我的一般步骤是先打开原图看文字清晰度再用OpenCV写几行代码把缩放、灰度化、直方图均衡化后的图片逐个测试找到能让检测稳定通过的预处理链路。这个过程虽然笨但最有效。4.2 could not create a primitiveONNX Runtime的线程问题搜索热词里有人提到“OCR could not create a primitive... no text detected”这类组合报错这个“could not create a primitive”报错我实际遇到过。它来自ONNX Runtime内部的OneDNN算子库通常和线程池配置或者CPU指令集有关。一种常见的触发方式是在Jupyter里反复运行实验或者和多线程库比如OpenCV同时使用线程池冲突导致创建原语失败。遇到这个报错我最先尝试的是限制线程数export OMP_NUM_THREADS1更彻底的做法是在Python脚本最顶部设置环境变量然后再导入RapidOCRimport os os.environ[OMP_NUM_THREADS] 1设置完重跑大多数情况下都能恢复正常。如果设置后问题依旧再看看是不是多个进程同时加载模型导致的内存压力适当减少并发Worker数量或者错峰加载模型。这类问题本质上都不是RapidOCR本身有bug而是运行环境层面的线程资源竞争。4.3 中文识别乱码、漏字与标点丢失中文OCR最常见的三个问题就是个别字识别错、长文本漏字、标点丢失。个别字识别错通常和图片质量直接相关。模糊、有噪声、字体过于艺术化都会导致某个字被识别成相似字形。这种情况调参很难根治如果业务场景固定建议走模型微调路线。漏字多半和检测框太紧有关。检测出的文本框如果没完整包住文字识别模型就只能看到半个字或者边缘残缺的字。可以通过适当放宽检测框或者在图像预处理时给文字区域增加留白来缓解。标点丢失尤其是中文全角标点是很多OCR模型的通病。如果业务对标点有硬性要求可以在后端加一个规则补充。比如识别结果里如果出现连续多个字却没有标点就根据上下文把常见的句读补上。这个方案听起来很土但在实际项目中确实能解决不少问题。4.4 CPU推理太慢怎么办在没有GPU的服务器上RapidOCR的CPU推理速度跟机器性能强相关。我的经验数据是一张1080P截图纯CPU推理大概在0.3到1秒之间算上图片解码和预处理整体延迟还在可控范围内。提速手段有优先级排序我建议按顺序尝试。第一是换用OpenVINO版本Intel CPU上通常有明显增益pip install rapidocr_openvino它的使用方式几乎和onnxruntime版本一致代码改动很小收益却很直接。第二是限制输入图片尺寸最大边不要超过2000像素超出部分先等比缩放。第三是关闭方向分类前提是你确认所有图片都是正向的。第四是批量处理场景用线程池并发调用OCR接口把多核CPU用起来。更推荐直接在Intel环境做OpenVINO版本替换因为代码改动几乎为零性能和稳定性提升却非常明显。5. 部署之后的一些实用扩展5.1 多语言与表格场景RapidOCR默认模型对中英文混排的支持相当好英文识别准确率也不低。但如果你要识别日文、韩文等其他语言可能需要到模型库找到对应语言模型进行替换默认模型覆盖不到这些场景。表格识别是另一个高频需求。RapidOCR本身只输出文字和坐标不负责表格结构还原。需要把输出的坐标信息按行分组、按列对齐再做结构化输出。我在项目里是自定义后处理逻辑实现的先按y坐标聚类成行再按x坐标排序成列最后根据单元格位置拼接出类表格数据结构。RapidOCR输出的坐标信息在这里非常关键这也是我特别喜欢它的原因之一坐标字段非常完整扩展性强。如果直接需要完整的表格还原能力可以把RapidOCR输出的检测框信息接入专门的表格结构分析模块二者互补能做出一个相当可用的表格OCR系统。5.2 与自动化工具联动搜索热词里有人提到“按键精灵本地ocr识别后点击”这个场景我很熟悉。把RapidOCR做成Web接口之后自动化工具只需要通过HTTP请求上传图片数据拿到返回的文字和坐标就能定位到目标区域执行点击操作。我在实际项目中就这么干过写了一个小服务监听一个目录新截图进入目录就自动调用RapidOCR把识别结果写入JSON文件另一个自动化脚本读取JSON后执行后续操作。整个过程完全本地化不依赖任何云OCR服务数据也不会外泄。这种模式的好处是门槛低、稳定、可控。自动化脚本只需要关心业务逻辑识别工作全都收敛到OCR服务这一层。哪怕后续要换OCR引擎也只是替换一个服务实现的问题上游完全无感。5.3 我的一些最终建议回头梳理这个项目我觉得最有价值的经验有三条。第一条选型时优先考虑部署成本别只盯着模型精度。精度再高部署不了就等于零。在“能跑起来”和“跑得漂亮”之间前者永远是第一优先级。第二条RapidOCR的版本API调整比较频繁网上很多教程的代码放到当前版本会报错。遇到问题和报错先确认自己安装的版本再查看对应版本的官方文档或源码比我这里写的文章更可靠。第三条也是最重要的OCR只是识别引擎真正的业务价值在后续的数据处理环节。坐标信息一定要充分利用它是连接“识别”和“业务”的桥梁。无论做自动点击、表格还原还是版面分析坐标都是绕不开的核心资产。
返回列表