资讯动态

麒麟V10 aarch64部署RapidOCR:内网环境完整踩坑与解决方案

发布时间:2026/9/9 7:19:27 来源:尧图企业网站定制
先说结论RapidOCR 在麒麟 V10aarch64上完全能跑起来但绝对不是“pip install 一下就完事”的项目。我在内网环境下整整折腾了两天半踩过平台不匹配、缺失系统动态库、模型自动下载失败、中文路径乱码这些坑最终把识别服务稳定跑起来了。这篇文章把整个过程和解决方案完整还原给后面要在国产化 ARM 环境上做 OCR 的朋友做个参考。这里说句掏心窝的话aarch64 环境最大的问题不是“装不上”而是很多 Python 包在 PyPI 上的 aarch64 wheel 并不全。尤其 onnxruntime 这种带原生代码的库装错一个版本就是连环坑。而麒麟 V10 又经常是内网环境没法临时去网上找依赖……所以这篇文章的核心思路是先弄懂每个组件在 aarch64 上的支持情况再决定怎么装。如果你正打算在麒麟 V10 / aarch64 上部署 RapidOCR或者已经装了一半卡在某个报错上这篇文章应该能帮你省下大半天的排查时间。1. 为什么最终选了 RapidOCR一次内网环境的 OCR 选型过程1.1 需求本身是什么我这次的场景比较简单一台麒麟 V10 服务器aarch64 架构CPU 是国产飞腾系列内存 16G无 GPU系统盘、数据盘都是常规配置。要做的事情是把一批扫描 PDF 和图片里的中文文字提取出来供后续系统检索和录入使用。因为是内网环境不能连接外网下载模型或依赖软件包来源受限这给部署增加了不少难度。1.2 主流 OCR 方案的对比部署前我先把市面主流的 OCR 方案在脑内过了一圈PaddleOCR识别效果确实好但 PaddlePaddle 框架本身比较大在 aarch64 上要么自己编译 paddlepaddle要么依赖官方提供的 whl。而且 PaddleOCR 完整安装后依赖很重对内存和磁盘要求高我这个 16G 内存的机器跑起来有点勉强部署体积也大。Tesseract安装简单但对中文识别的精度一般尤其遇到复杂排版、倾斜文本、低清扫描件时效果明显不如基于深度学习模型的方案。训练自己的模型又需要额外工作量。商用 OCR识别效果好但需要联网调用或授权内网环境下合规和成本都是问题。最后选了 RapidOCR。这个项目最吸引我的点是它把 PaddleOCR 的模型转换成了 ONNX 格式推理时不需要装 PaddlePaddle只需要 onnxruntime 这一个带原生代码的推理引擎。这就把“安装 Paddle 全家桶”的问题缩小成了“搞定 onnxruntime 一个包”的问题。更重要的是RapidOCR 对运行环境要求低纯 CPU 就能跑非常适合内网服务器这种没有 GPU 的场景。1.3 RapidOCR 的组件和部署形态RapidOCR 并不是一个单体程序而是一套组件的组合。核心是三个模型文件检测模型det负责框出文本区域方向分类模型cls负责把旋转的文本方向纠正识别模型rec负责把文本区域转换成字符。三个模型都是 .onnx 格式由 Python 包 rapidocr_onnxruntime 统一加载调用。封装形式上RapidOCR 提供了 Python API 和命令行工具实际使用中以 Python API 居多。对于我这个项目最终要把它封装成一个 HTTP 服务供业务系统调用。这个部署形态决定了我在后续操作中要格外注意模型加载次数、并发处理方式、内存占用等问题。因为一旦做成服务就不是“跑一条命令行”那么简单了。2. 动手前先摸清家底麒麟 V10 (aarch64) 环境检查2.1 系统版本与 CPU 架构确认拿到机器第一件事不是急着装包而是先把系统信息摸清楚。我用下面几条命令确认了基本盘cat /etc/os-release uname -m cat /proc/cpuinfo | grep -E model name|processor | head -n 20uname -m输出是aarch64确认这是 64 位 ARM 架构和常见的 x86_64 完全不同。/etc/os-release显示麒麟 V10 的某个 SP 版本。/proc/cpuinfo显示处理器是飞腾系列支持的指令集是 armv8 这一档。这里为什么要强调“先看架构”因为 aarch64 环境下很多 pip 包默认下载到的 wheel 可能是为 x86_64 编译的硬装会直接报not a supported wheel on this platform。系统源、Python 版本、动态库情况也都要以 aarch64 为准去评估。2.2 Python 和 pip 环境的坑麒麟 V10 系统自带的 Python 版本通常比较老不同 SP 版本带的 Python 3 版本不完全一样。我建议在部署 RapidOCR 前先确认当前的 Python 和 pip 版本python3 --version pip3 --version如果系统自带 Python3 版本太旧比如 3.6尽量用系统包管理装一个新一点的 Python3或者找内网源里现成的更高版本。RapidOCR 官方对 Python 版本有要求太老的 Python 版本会导致某些依赖的 wheel 不存在或者语法不兼容。还有个容易忽略的点pip 默认源。在内网环境里如果不配置内网 pip 源pip install 会一直卡在连接超时上。配置方法很简单mkdir -p ~/.pip cat ~/.pip/pip.conf EOF [global] index-url http://内网pip源地址/simple trusted-host 内网pip源地址 EOF如果没有内网 pip 源那就只能在有外网的机器上把依赖包下载成 whl 文件再用pip install --no-index --find-links/路径 whl文件离线安装。这一步在后面模型下载那部分还会遇到。2.3 内网环境下如何准备依赖内网部署最忌讳“边装边找包”。我给自己的规矩是先在测试环境把依赖梳理清楚再打包搬运到目标机。这一步可以在外网或者有网的机器上做pip download rapidocr_onnxruntime -d /tmp/rapidocr_pkgs --platform manylinux2014_aarch64 --only-binary:all:加--platform manylinux2014_aarch64和--only-binary:all:能确保下载的是 aarch64 的预编译 wheel而不是源码包。如果你是 x86_64 机器上现跑的 Python 环境直接pip download可能下载到 x86_64 的包到目标机后装不上所以这个平台参数一定要加。下载完成后把整个目录拷贝到内网机器上再用pip install --no-index --find-links/tmp/rapidocr_pkgs rapidocr_onnxruntime安装。注意--no-index一定要加否则 pip 仍会试图访问外网源。如果内网机器还需要通过固定路由访问某些服务别忘了提前确认路由表避免依赖包下好了却传不进目标机这种尴尬事。3. 安装阶段最大的坑onnxruntime 的 aarch64 支持3.1 直接 pip 安装会得到什么我在测试机上有网环境下直接执行了pip install rapidocr_onnxruntime结果装完之后导入时没报错用户还挺高兴。但一到执行识别onnxruntime 初始化 InferenceSession 的时候直接抛了异常具体的错误信息大概类似Failed to load library或者Error at inference。这种问题往往不是 RapidOCR 本身的问题而是 onnxruntime 安装的版本和系统动态库不匹配。后来把 onnxruntime 卸载重装指定版本才解决。所以我的建议是在 aarch64 上不要让 pip 自动解析 onnxruntime 版本必须显式指定一个你验证过的版本。3.2 定位问题是平台标签不匹配如果手动下载 wheel 文件最容易翻车的就是平台标签不匹配。比如在内网机器上执行pip install onnxruntime-1.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whlpip 会直接提示ERROR: onnxruntime-1.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl is not a supported wheel on this platform这种情况在 aarch64 上非常典型。下载 whl 前先看文件名比如onnxruntime-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl看到aarch64字样才对。还有一种情况是 Python 版本和 whl 的 cp 标签不匹配。例如你的 Python 是 3.8却下了 cp39 的包pip 同样会拒绝安装。下载前先python3 -V确认版本然后下载对应 cp 标签的 whl。3.3 正确安装方式和版本选择在多次尝试后我确定下来一套稳定的版本组合这里直接给结论Python 3.8 或 3.9onnxruntime1.15.1aarch64 manylinux 版本注意不同版本对 glibc 版本有要求opencv-python-headless不要装 opencv-python服务器没有 GUI 时 opencv-python 会缺 libGL.so.1numpy 版本不要太高1.24 左右比较稳避免和 onnxruntime 的 ABI 冲突安装命令pip install numpy1.24.4 pip install onnxruntime1.15.1 pip install opencv-python-headless pip install rapidocr_onnxruntime提示上述版本组合是我在飞腾平台上验证过的。如果你用的是鲲鹏 CPU 或者更新的 SP 版本onnxruntime 版本可以适当上调但改动后必须重新压测识别效果不要直接上生产。这里解释一下为什么 opencv 一定要用 headless 版本麒麟 V10 服务器版通常没有安装桌面环境和 X11 相关库opencv-python 自带的 cv2 在导入时会去加载 libGL.so.1找不到就报 ImportError。headless 版本则去掉了 GUI 相关依赖只保留图像处理和编解码能力正好满足 OCR 场景。3.4 还需要装哪些系统依赖libgomp 等onnxruntime 在 aarch64 上还依赖 OpenMP 运行时库 libgomp。如果系统里没有这个库导入 onnxruntime 时会报ImportError: libgomp.so.1: cannot open shared object file: No such file or directory这个错误很典型。解决方法是yum install -y libgomp如果 yum 源里搜不到可以试yum search libgomp或者从安装光盘、内网 yum 仓库里找对应的 aarch64 rpm 包。这个库很小但漏掉它时排查起来特别隐蔽因为它不是 Python 包很多人会以为只是编译问题。4. 模型文件内网下发RapidOCR 自动下载模型的“隐形依赖”4.1 首次运行会触发模型下载RapidOCR 首次运行时如果检测不到模型文件会自动从远程仓库下载三个 .onnx 模型文件。外网环境可能无感但在内网环境下这一步会一直卡住或者超时。具体表现是执行engine RapidOCR()之后日志显示正在下载模型然后长时间无响应。如果网络完全不通最终会报连接失败。这种“运行时报错”比安装报错更难定位因为你可能以为代码没问题实际上是模型文件缺失。4.2 模型文件的获取与手动放置解决方法是提前在有外网的机器上下载好模型文件。RapidOCR 的 GitHub Releases 页面提供了包含三个模型文件的压缩包下载后解压会得到类似下面的结构models/ ch_PP-OCRv3_det_infer.onnx ch_PP-OCRv3_rec_infer.onnx ch_ppocr_mobile_v2.0_cls_infer.onnx把这几个文件拷贝到内网机器上。放置位置有两种选择放到 Python 环境中 RapidOCR 包自带的 models 目录下替换或补齐同名文件。这种方式的优点是简单代码不用改缺点是升级包时要留意模型是否被覆盖。放到自定义目录创建 RapidOCR 实例时通过参数指定模型路径。这种方式更灵活适合多环境部署。RapidOCR 初始化时如果指定了模型路径就不会再触发自动下载。推荐用第二种方式因为部署到多台机器时模型和代码可以分开管理。4.3 模型版本和代码版本必须匹配这是一个很容易被忽视的坑。RapidOCR 的 Python 包版本和模型文件版本是有对应关系的如果代码升级了但模型还是旧版或者反过来可能会出现推理输出异常、shape 不匹配等莫名其妙的问题。我遇到过一次把 RapidOCR 从 1.2.x 升到 1.3.x 后检测模型还是老的结果输出结果里的坐标框明显偏移。最后重新下载配套模型文件才恢复正常。所以换版本时一定把 Python 包和模型文件当作一个整体来更新不要只改一半。5. 运行时报错的完整排查链路从 import 到第一次推理5.1 ImportError: libgomp.so.1: cannot open shared object file这个坑前面提过但排查过程值得展开说一下。我当时的报错链路是这样的python3 -c import onnxruntime输出ImportError: libgomp.so.1: cannot open shared object file: No such file or directory第一反应是重新装 onnxruntime但没用。用ldd查看 onnxruntime 的 so 文件依赖ldd /usr/local/lib/python3.8/site-packages/onnxruntime/capi/libonnxruntime.so | grep not found发现只有 libgomp.so.1 找不到。这时候才明白不是 Python 包的问题而是系统的动态库缺失。用yum install -y libgomp装好后再执行ldd所有依赖项都正常了。这个排查思路适用于任何“Python 包导入时报找不到 so 文件”的情况先用 ldd 定位缺哪个库再有针对性地装系统包不要盲目重装 Python 包。5.2 UnicodeDecodeError / 中文路径问题模型能加载了接着测识别。第一张测试图片路径是/data/测试图片/发票.jpg执行识别时报了 UnicodeDecodeError 或者图片读取失败。原因在于 OpenCV 的cv2.imread在部分 Linux 环境下对中文路径支持不好会返回 None导致后续处理崩溃。RapidOCR 内部如果直接用 cv2 读图会遇到这个问题。解决办法是提前将图片读取为 numpy 数组再传给 RapidOCRimport cv2 import numpy as np from rapidocr_onnxruntime import RapidOCR engine RapidOCR() def read_image(path): img cv2.imdecode(np.fromfile(path, dtypenp.uint8), cv2.IMREAD_COLOR) return img img read_image(/data/测试图片/发票.jpg) result engine(img)这样完整绕过了中文路径问题。这个技巧在业务系统对接时特别常用因为业务文件路径往往带着中文目录名。5.3 输入图片和预处理细节RapidOCR 对输入图片有一些基本要求图片太小或者大片空白区域时检测框定位可能失败纯白底图片直接返回空结果。这在测试时容易误判为“部署失败”其实是图片本身没有可识别的文字。另外如果图片是 RGBA 四通道格式部分版本会提示不支持或识别异常最好统一转成 BGR 或 RGBif img.shape[2] 4: img cv2.cvtColor(img, cv2.COLOR_RGBA2BGR)这类预处理逻辑建议封装在统一接口里而不是每次调用时临时处理。业务方传过来的图五花八门有截图、有手机拍照、有扫描件统一走同一个预处理入口遇到问题也好排查。6. 性能实测与调优让 CPU 推理从“吃力”到“够用”6.1 线程数设置aarch64 处理器核心数通常不少但 onnxruntime 默认的线程调度未必能充分利用。在初始化 RapidOCR 时可以设置 intra_op_num_threads控制推理时使用的线程数。以我使用的版本为例engine RapidOCR(intra_op_num_threads4)如果用的版本支持这个参数直接传即可不支持的话也可以在初始化 onnxruntime 的 session options 里设置。线程数不是越大越好实测 4 到 8 个线程时性能提升最明显再往上会受内存带宽影响收益递减。6.2 量化模型替换RapidOCR 官方提供了量化后的模型文件文件名通常带_quant后缀比如ch_PP-OCRv3_det_infer_quant.onnx。量化模型体积更小、推理速度更快识别精度略有下降但大多数场景下可接受。我的做法是先用原始模型跑通流程确认识别效果满足需求后再替换成量化模型压测性能。如果精度下降在可接受范围就切换到量化版毕竟内网服务器的 CPU 资源也要考虑给其他业务留一部分。6.3 实测耗时数据下面是我在飞腾 CPU8 核心上的一组粗略测试数据供参考。测试图片是一张 A4 大小、包含约 200 个汉字的扫描截图单张识别。模型类型线程数单张耗时原始模型4约 2.1 秒原始模型8约 1.6 秒量化模型4约 1.2 秒量化模型8约 0.9 秒这个数据不是 CPU 满负载时测的实际业务高峰可能更慢。但对比来说量化模型 8 线程的组合在性能和准确率之间比较平衡能满足大多数后台 OCR 场景。6.4 批量场景的优化策略如果业务是批量处理几百张图片不要每次新建一个 RapidOCR 实例那样会反复加载模型、白白浪费内存和 IO。正确做法是全局只初始化一个实例循环调用engine RapidOCR(intra_op_num_threads4) for img in img_list: result engine(img) # 处理结果实测下来复用实例比每次新建实例在批处理场景下能快近一倍因为没有反复加载模型文件的开销。这一步优化代码改动很小收益却很明显。7. 服务化部署封装成 HTTP 接口的经验7.1 FastAPI 封装识别能力调通之后最终要提供给业务系统调用。RapidOCR 本身是 Python API最直接的方式是用 FastAPI 包一层 HTTP 接口。示例代码如下import base64 import cv2 import numpy as np from fastapi import FastAPI from pydantic import BaseModel from rapidocr_onnxruntime import RapidOCR app FastAPI() engine RapidOCR(intra_op_num_threads4) class OCRRequest(BaseModel): image_base64: str app.post(/ocr) def ocr(req: OCRRequest): img_bytes base64.b64decode(req.image_base64) img_array np.frombuffer(img_bytes, dtypenp.uint8) img cv2.imdecode(img_array, cv2.IMREAD_COLOR) result engine(img) texts [item[1] for item in result[0]] if result[0] else [] return {texts: texts}这样调用方只需要把图片转成 base64 传过来服务端解析、识别、返回结构化文本整个链路简单清晰。7.2 uvicorn 和 systemd 开机自启服务封装好后用 uvicorn 启动uvicorn ocr_service:app --host 0.0.0.0 --

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价