基于 TVM 与 Arm Virtual Hardware 在 Cortex(R)-M55 裸机环境运行 PaddleOCR 文本识别模型实战指南
2026/9/18 21:59:46 网站建设 项目流程

基于 TVM 与 Arm Virtual Hardware 在 Cortex(R)-M55 裸机环境运行 PaddleOCR 文本识别模型实战指南

【免费下载链接】PaddleOCR飞桨多语言OCR工具包(实用超轻量OCR系统,支持80+种语言识别,提供数据标注与合成工具,支持服务器、移动端、嵌入式及IoT设备端的训练与部署) Awesome multilingual OCR toolkits based on PaddlePaddle (practical ultra lightweight OCR system, support 80+ languages recognition, provide data annotation and synthesis tools, support training and deployment among server, mobile, embedded and IoT devices)项目地址: https://gitcode.com/paddlepaddle/PaddleOCR

导读:本文以 PaddleOCR 仓库 deploy/avh 目录下的官方示例为主线,完整讲解如何借助 Apache TVM 将 PaddleOCR 的 PP-OCRv3 英文文本识别模型(裁剪后约 2.7M)编译为面向 Arm(R) Cortex(R)-M55 CPU 与 CMSIS-NN 后端的裸机可执行程序,并分别在 Arm Virtual Hardware(AVH)云端 AMI 实例与本地 FVP 仿真器上运行、输出识别文字与置信度。读完本文,你将掌握完整的嵌入式侧 OCR 模型部署链路:环境准备 → TVM 编译 → 图像数据 C 数组化 → 裸机构建 → 仿真运行,并可直接替换为自己的图片与模型进行验证。

一、方案背景:为什么要在 AVH 上跑 PaddleOCR

Arm Virtual Hardware(AVH)是 Arm 提供的虚拟硬件仿真平台,可以在没有真实物理开发板的情况下,基于 Arm(R) Corstone(TM)-300 软件(Fixed Virtual Platform,FVP)模拟 Cortex(R)-M55 CPU 等嵌入式内核的执行行为。它的价值在于:

  • 提前验证嵌入式部署方案:在硬件到位之前即可验证模型编译、算子兼容性与推理流程;
  • 可复现的 CI 环境:与 TVM 生态中的 ci_cpu Docker 容器配合,适合做自动化回归验证;
  • 降低嵌入式开发门槛:不需要购买开发板、不需要手动搭建交叉编译环境,脚本可一键完成。

本示例的技术栈是「PaddleOCR(模型侧)+ TVM(编译侧)+ CMSIS-NN(算子库)+ AVH/FVP(运行侧)」:先用 TVM 的tvmc把 PaddlePaddle 推理模型编译成面向 Cortex-M55 的 C 代码(AOT 执行器、CRT 运行时),再通过arm-none-eabi-gcc交叉编译出裸机可执行文件,最后在 AVH 平台上运行并打印识别结果。

二、运行环境与前置依赖

原文档给出了三种运行场景,依赖准备方式各不相同,这里逐一说明。

场景一:Arm Virtual Hardware AMI 云实例(推荐,零手工依赖)

如果运行在 AWS / AWS China 市场提供的Arm Virtual Hardware Amazon Machine Image(AMI)实例中,所需的软件会在执行run_demo.sh时通过 configure_avh.sh 脚本自动安装,无需手工干预。

从 configure_avh.sh 的源码可以看到它依次完成四件事:

  1. 安装 CMSIS:下载指定 SHA 提交(977abe9849781a2e788b02282986480ff4e25ea6)的 CMSIS_5,解压到/opt/arm/ethosu/cmsis,并用sha512sum -c校验完整性;
  2. 安装 Arm(R) Ethos(TM)-U NPU driver stackgit cloneethos-u-core-platform 到/opt/arm/ethosu/core_platform并 checkout 到21.11tag;
  3. 安装 Arm(R) GNU Toolchain:下载gcc-arm-none-eabi-10-2020-q4-major并解压到/opt/arm/gcc-arm-none-eabi
  4. 安装 TVM:通过pip install tlcpack-nightly从 TLCPack 安装预编译 TVM。

场景二:TVM 提供的 ci_cpu Docker 容器

TVM 官方仓库的Dockerfile.ci_cpu容器中已预装上述全部软件,直接docker run进入容器后即可使用,无需再装任何依赖。

场景三:本地裸机环境(完全手动)

如果既不用 AMI 也不用 Docker 容器,需要手动准备:

  • 构建与运行所需软件(可通过 TVM 仓库的ubuntu_install_ethosu_driver_stack.sh一键安装):
    • 基于 Arm(R) Corstone(TM)-300 的 Fixed Virtual Platform(FVP)仿真器;
    • cmake 3.19.5;
    • Arm(R) GCC 工具链(gcc-arm-none-eabi-10-2020-q4-major);
    • Arm(R) Ethos(TM)-U NPU driver stack;
    • CMSIS(CMSIS_5)。
  • Python 依赖:本目录下的 requirements.txt 定义了四个包,在deploy/avh目录下执行:
pip install -r ./requirements.txt
  • TVM:二选一:
    • 从 TLCPack 安装预编译包;
    • 从源码构建 TVM。若从源码构建,必须在config.cmake中开启以下三个开关,否则后续编译无法完成:
      • set(USE_CMSISNN ON)
      • set(USE_MICRO ON)
      • set(USE_LLVM ON)

环境变量配置

在场景二、场景三中,需要把 cmake 3.19.5 与 FVP 的路径加入PATH。假设安装在/opt/arm下:

export PATH=/opt/arm/FVP_Corstone_SSE-300/models/Linux64_GCC-6.4:/opt/arm/cmake/bin:$PATH

提示:路径中的FVP_Corstone_SSE-300即 Corstone-300 对应的 FVP 模型目录,Linux64 下实际可执行程序位于其models/Linux64_GCC-6.4子目录。

三、一键运行 Demo:run_demo.sh

deploy/avh目录下执行:

./run_demo.sh

如果无法使用 AWS/AWS China 提供的 AVH AMI 实例,可以追加--enable_FVP 1参数,改用本地 FVP 可执行程序运行:

./run_demo.sh --enable_FVP 1

如果 Ethos(TM)-U 平台和/或 CMSIS 没有安装在默认位置/opt/arm/ethosu,可通过参数显式指定:

./run_demo.sh --cmsis_path /home/tvm-user/cmsis \ --ethosu_platform_path /home/tvm-user/ethosu/core_platform

从 run_demo.sh 源码的show_usage可以看到它支持的全部参数:

参数说明默认行为
-h, --help打印帮助信息
--cmsis_path CMSIS_PATH设置 CMSIS 路径/opt/arm/ethosu/cmsis
--ethosu_platform_path ETHOSU_PLATFORM_PATH设置 Ethos(TM)-U core platform 路径/opt/arm/ethosu/core_platform
--fvp_path FVP_PATH设置 FVP 路径(脚本会自动拼接models/Linux64_GCC-6.4环境变量PATH
--cmake_path设置 cmake 路径(导出为CMAKE供 Makefile 使用)cmake
--enable_FVP置 1 时改用本地 FVP 执行(合法取值为 1 或 0)0(默认走 AVH)

脚本本身还做了几件额外的事情:

  • 脚本开头执行sudo pip install -r ./requirements.txt安装 Python 依赖;
  • 默认将gcc-arm-none-eabi的 bin 目录加入PATHexport PATH=/opt/arm/gcc-arm-none-eabi/bin:$PATH);
  • 非 FVP 模式下,若/opt/arm/不存在,则自动调用sudo ./configure_avh.sh完成环境初始化;
  • 根据--enable_FVP选择运行平台名:VHT_Corstone_SSE-300_Ethos-U55(AVH 云端)或FVP_Corstone_SSE-300_Ethos-U55(本地)。

四、run_demo.sh执行的完整链路

原文档列出了脚本的七个步骤,结合 run_demo.sh 源码可以还原每一步的具体命令:

  1. 设置运行环境:AMI 场景下通过configure_avh.sh自动安装前置软件(见上文);
  2. 下载 PaddleOCR 文本识别模型wget https://paddleocr.bj.bcebos.com/tvm/ocr_en.tar并解压,得到 Paddle 推理模型ocr_en/inference.pdmodel
  3. 使用 tvmc 将模型编译为 Cortex(R)-M55 CPU + CMSIS-NN 后端:完整编译命令如下:
python3 -m tvm.driver.tvmc compile --target=cmsis-nn,c \ --target-cmsis-nn-mcpu=cortex-m55 \ --target-c-mcpu=cortex-m55 \ --runtime=crt \ --executor=aot \ --executor-aot-interface-api=c \ --executor-aot-unpacked-api=1 \ --pass-config tir.usmp.enable=1 \ --pass-config tir.usmp.algorithm=hill_climb \ --pass-config tir.disable_storage_rewrite=1 \ --pass-config tir.disable_vectorize=1 ocr_en/inference.pdmodel \ --output-format=mlf \ --model-format=paddle \ --module-name=rec \ --input-shapes x:[1,3,32,320] \ --output=rec.tar

其中关键选项含义如下:

  • --target=cmsis-nn,c:生成两级 target,算子优先落到 CMSIS-NN,其余落为纯 C 代码;
  • --runtime=crt:使用 TVM 的 C Runtime(C Runtime / CRT),配合裸机环境;
  • --executor=aot--executor-aot-interface-api=c--executor-aot-unpacked-api=1:生成 AOT(Ahead-Of-Time)执行器,C 接口、非打包参数传递,便于嵌入式端直接调用;
  • --pass-config tir.usmp.enable=1tir.usmp.algorithm=hill_climb:启用 Unified Static Memory Planner,用 hill climb 算法做静态内存规划,减少片上内存占用;
  • --input-shapes x:[1,3,32,320]:指定输入张量x的形状为 NCHW(batch=1, channel=3, height=32, width=320),与 PP-OCRv3 识别模型的预处理尺寸一致;
  • --model-format=paddle:声明输入为 PaddlePaddle 推理模型;
  • --module-name=rec:生成的入口函数命名为tvmgen_rec_run(下文 C 代码中会用到)。

编译产物rec.tar解压后是 TVM 的 Model Library Format(MLF)包,内含codegen/host/src的生成 C 代码与 CRT 运行时源码,供 Makefile 构建使用。

  1. 生成输入 C 头文件:调用python3 ./convert_image.py imgs_words_en/word_116.png,把示例图片转换成inputs.h中的 C 数组;
  2. 生成输出 C 头文件convert_image.py同时生成outputs.h,预分配长度为 7760 的 float 输出数组;
  3. 构建 Demo 可执行程序:执行make(详细构建过程见第六节);
  4. 在 AVH 上运行:按平台名执行仿真器,并传入一系列-C配置参数:
$Platform -C cpu0.CFGDTCMSZ=15 \ -C cpu0.CFGITCMSZ=15 -C mps3_board.uart0.out_file=\"-\" -C mps3_board.uart0.shutdown_tag=\"EXITTHESIM\" \ -C mps3_board.visualisation.disable-visualisation=1 -C mps3_board.telnetterminal0.start_telnet=0 \ -C mps3_board.telnetterminal1.start_telnet=0 -C mps3_board.telnetterminal2.start_telnet=0 -C mps3_board.telnetterminal5.start_telnet=0 \ ./build/demo --stat

其中cpu0.CFGDTCMSZ=15/cpu0.CFGITCMSZ=15设置 CPU 的 Data/Instruction TCM(紧耦合内存)大小为 2^15 字节(32KB),UART 输出重定向到标准输出,并约定收到EXITTHESIM字样即结束仿真。程序运行后会在终端输出图片上的文字与对应的置信度(score)。

五、使用自己的图片与模型

更换输入图片

convert_image.py 接收一个命令行参数——图片路径,将其转换为模型可直接消费的字节数组:

python3 ./convert_image.py path/to/image

修改run_demo.sh中调用convert_image.py的那一行即可替换为任意图片。参考源码,图像预处理与 C 数组化的完整逻辑为:

  • 读取图片后调用resize_norm_img(img, [3, 32, 320]),将其等比缩放到高度 32,若等比宽度超过 320 则截断为 320,否则在右侧补零(padding);
  • 像素值除以 255 归一化到[0,1],再执行(x - 0.5) / 0.5标准化到[-1,1]
  • 转为 CHW 布局并np.expand_dims增加 batch 维,得到[1,3,32,320]的输入;
  • 通过create_header_file写入deploy/avh/include/inputs.h,数据以__attribute__((section(".data.tvm"), aligned(16)))的 float 数组形式存放;
  • 同时生成outputs.houtput_data = np.zeros([7760], np.float32),即输出缓冲区长度为 7760 = 字符序列长度(80)× 词典大小(97)。

仓库自带的示例输入图(位于 deploy/avh/imgs_words_en 目录)为清晰无干扰的英文单词图,例如默认使用的word_116.png,文字内容为 "QBHOUSE",适合作为 OCR 输入验证:

更换模型

run_demo.sh中替换下载/解压 Paddle 推理模型的那一处(约 130 行附近,即wgettar步骤)即可换用其他 PaddleOCR 模型。需要注意:模型必须与 Cortex-M55 的算子能力兼容——例如 RNN 类算子当前无法在 Cortex-M55 上运行(详见第七节),更换模型时需保证其算子集合在 TVMcmsis-nn,ctarget 下可编译通过,且输入形状要与--input-shapes参数一致。

六、裸机程序构建与运行原理(源码级剖析)

Makefile 构建骨架

Makefile 把上一节 tvmc 生成的 MLF 产物、CMSIS 启动代码与示例主程序链接成build/demo

  • 交叉编译器固定为arm-none-eabi-gcc,编译选项包含-mcpu=cortex-m55 -mthumb -mfloat-abi=hard,即针对 Cortex-M55 的硬浮点 Thumb 代码;
  • 头文件搜索路径覆盖:TVM CRT 运行时(build/runtime)、CMSIS Device/Core/NN/DSP 头、Corstone-300 平台头、deploy/avh/include(即inputs.h/outputs.h)以及 tvmc 生成的codegen/host/include
  • CMSIS-NN 通过 CMake 交叉编译(使用 arm-none-eabi-gcc.cmake 工具链文件,TARGET_CPU=cortex-m55,开启BUILD_CMSIS_NN_FUNCTIONS=YES)得到libcmsis-nn.a
  • 链接参数包含-T corstone300.ld(链接脚本)与-specs=nosys.specs,面向无操作系统的裸机目标;
  • 链接的库还包括 CRT 的stack_allocator.ocrt_backend_api.o、TVM 生成的libcodegen.a以及 CMSIS 启动代码libcmsis_startup.a

主程序:推理与后处理

裸机主程序 demo_bare_metal.c 完整演示了嵌入式端调用 AOT 执行器的标准写法:

#include <tvm_runtime.h> #include <tvmgen_rec.h> // tvmc 以 --module-name=rec 生成 #include "inputs.h" // convert_image.py 生成 #include "outputs.h" struct tvmgen_rec_inputs rec_inputs = { .x = input }; struct tvmgen_rec_outputs rec_outputs = { .output = output }; tvmgen_rec_run(&rec_inputs, &rec_outputs);

推理完成后,程序在 MCU 内部直接完成 CTC 式解码:

  • 词典为 97 个字符(dict[]),输出数组长度 7760 = 时间步数 × 97,每个时间步对 97 类取 argmax;
  • 跳过argmax_idx == 0(空字符/blank),并去除相邻重复字符(argmax_idx == last_index时不输出),这正是 CTC 解码「去重 + 去 blank」的核心逻辑;
  • 将保留字符的置信度求平均作为整句 score,最终通过 UART 打印text: <识别文字>, score: <置信度>
  • 最后打印EXITTHESIM触发 FVP 仿真退出,然后进入while(1)死循环挂起。

从这段代码可以直观理解:整个推理与解码流程在裸机端完成,无需操作系统,这正是 TVM AOT + CRT 在嵌入式端部署的典型形态。

七、模型说明:面向 Cortex-M55 裁剪的 PP-OCRv3 英文识别模型

本示例默认使用基于PP-OCRv3英文识别模型裁剪得到的约2.7M模型(下载自paddleocr.bj.bcebos.com/tvm/ocr_en.tar)。之所以需要裁剪,是因为Arm(R) Cortex(R)-M55 CPU 不支持 RNN 算子,而 PP-OCRv3 原始识别模型中含有 RNN(如 BiLSTM)结构;工程上删除不支持的算子后,得到当前这个约 2.7M 的英文识别模型。

PP-OCRv3 是 PaddleOCR 发布的 PP-OCR 系列第三代模型,仓库文档 docs/version2.x/ppocr/blog/PP-OCRv3_introduction.md 详细介绍了其特性,这里摘要三点与本示例强相关的:

  • 超轻量级 OCR 系统:检测(3.6M)+ 方向分类器(1.4M)+ 识别(12M)= 17.0M,整体模型体积小,适合边缘/嵌入式部署;
  • 多语言支持:支持 80+ 种多语言识别模型,包括英文、中文、法文、德文、阿拉伯文、韩文、日文等;本示例即面向英文识别场景;
  • 能力覆盖广:支持竖排文本识别与长文本识别。

可以推断:只要满足算子兼容与输入尺寸约束,PP-OCRv3 系列其他语言/能力的识别模型同样具备移植到本示例链路的潜力。

八、注意事项与常见问题

  • 算子兼容性是硬约束:Cortex-M55 上无法直接运行含 RNN 的模型,选型或裁剪模型时必须确认算子集合在cmsis-nn,ctarget 下可编译(可用tvmc compile提前验证);
  • 输入形状必须对齐--input-shapes x:[1,3,32,320]convert_image.py中的resize_norm_img(img, [3, 32, 320])必须一致,更换模型时两者需同步修改;
  • AVH 与 FVP 的差异:默认走 AVH 云端 AMI;本地环境需--enable_FVP 1并保证 FVP 已安装、路径已加入PATH
  • 默认安装路径:CMSIS 与 Ethos-U core platform 默认安装在/opt/arm/ethosu/下,非此路径时必须用--cmsis_path/--ethosu_platform_path显式指定;
  • TVM 构建开关:从源码构建 TVM 时,务必开启USE_CMSISNNUSE_MICROUSE_LLVM三个选项,否则 tvmc 无法完成cmsis-nn,ctarget 的编译;
  • 验证步骤建议:先跑通默认的word_116.png,确认输出与置信度正常后,再替换为自己的图片与模型,逐项排查。

九、总结

本文从 deploy/avh/README.md 出发,结合 run_demo.sh、convert_image.py、demo_bare_metal.c、Makefile 与 configure_avh.sh 等源码,完整还原了「PaddleOCR 模型 → TVM 编译 → 裸机程序 → AVH/FVP 仿真运行」的嵌入式 OCR 部署链路。这套方案的核心价值在于:开发者可以在没有实体开发板的条件下,以最小成本验证 PaddleOCR 模型在 Cortex-M 系列嵌入式平台上的可用性与推理效果,为后续的真实硬件移植(如基于 Ethos-U NPU 的加速部署)打下坚实基础。

【免费下载链接】PaddleOCR飞桨多语言OCR工具包(实用超轻量OCR系统,支持80+种语言识别,提供数据标注与合成工具,支持服务器、移动端、嵌入式及IoT设备端的训练与部署) Awesome multilingual OCR toolkits based on PaddlePaddle (practical ultra lightweight OCR system, support 80+ languages recognition, provide data annotation and synthesis tools, support training and deployment among server, mobile, embedded and IoT devices)项目地址: https://gitcode.com/paddlepaddle/PaddleOCR

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询