当前位置: 首页 > news >正文

PP-OCR的安卓端部署

EMO了几天

我浪费了几天的生命,去研究PP-OCR的模型微调、从训练模型导出预测模型,结果一个坑接着一个坑,没有善终。
找了好多资料,得到一些负面信息,比如说飞浆的团队修复问题不及时啦,代码仓库有好多年不更新啦,为了KPI而搞开源啦等等。
今天想着还是先把安卓端部署过程记录下来吧,忘掉那些不开心吧。

安卓端部署简介

如果直接用官方提供的模型去跑,其实还是挺香的,OCR是飞浆框架下最厉害的库了。
安卓部署官方也有demo的(当然是几年前的),PaddleOCR–deploy下去找,我也放到csdn下载了。

例子中使用的PP-OCRv2的模型,想想现在都PP-OCRv4了,是不是心中着急?

PaddleLite

想要在安卓端部署,需要飞浆下的另一个重要的库,PaddleLite。
Paddle Lite 是百度飞桨(PaddlePaddle)生态中的端侧推理引擎,专注于在移动设备、嵌入式设备和边缘计算场景中实现高效的深度学习模型部署。其核心目标是通过轻量化、高性能的优化技术,降低模型运行时的资源消耗,同时支持多种硬件平台和操作系统。
Demo中使用的是2.10版本,目录结构如下:

OpenCV

OpenCV的作用自然在负责图像处理部分。在安卓平台,它的用途还真是广泛的不得了。
Demo中使用的是4.2.0,目录结构如下:

PaddleOCR的模型和字典

模型文件和字典是程序运行后下载的,如下图:

App源码简介

代码结构依然是Java层+Native层。

Java代码

上层的业务逻辑,以及通过JNI调用Native层代码。结构如下:

Java层与Native层沟通仅仅用了三个方法,它们在OCRPredictorNative类中:

    protected native long init(String detModelPath, String recModelPath, String clsModelPath, int useOpencl, int threadNum, String cpuMode);protected native float[] forward(long pointer, Bitmap originalImage,int max_size_len, int run_det, int run_cls, int run_rec);protected native void release(long pointer);

Native层代码

源码结构如下图:

JNI的实现在native.cpp中,重点看forward方法的实现,OCR的处理逻辑及返回结果都在这里了。

extern "C" JNIEXPORT jfloatArray JNICALL
Java_com_baidu_paddle_lite_demo_ocr_OCRPredictorNative_forward(JNIEnv *env, jobject thiz, jlong java_pointer, jobject original_image,jint j_max_size_len, jint j_run_det, jint j_run_cls, jint j_run_rec) {LOGI("begin to run native forward");if (java_pointer == 0) {LOGE("JAVA pointer is NULL");return cpp_array_to_jfloatarray(env, nullptr, 0);}cv::Mat origin = bitmap_to_cv_mat(env, original_image);if (origin.size == 0) {LOGE("origin bitmap cannot convert to CV Mat");return cpp_array_to_jfloatarray(env, nullptr, 0);}int max_size_len = j_max_size_len;int run_det = j_run_det;int run_cls = j_run_cls;int run_rec = j_run_rec;ppredictor::OCR_PPredictor *ppredictor =(ppredictor::OCR_PPredictor *)java_pointer;std::vector<int64_t> dims_arr;std::vector<ppredictor::OCRPredictResult> results =ppredictor->infer_ocr(origin, max_size_len, run_det, run_cls, run_rec);LOGI("infer_ocr finished with boxes %ld", results.size());// 这里将std::vector<ppredictor::OCRPredictResult> 序列化成// float数组,传输到java层再反序列化std::vector<float> float_arr;for (const ppredictor::OCRPredictResult &r : results) {float_arr.push_back(r.points.size());float_arr.push_back(r.word_index.size());float_arr.push_back(r.score);// add det pointfor (const std::vector<int> &point : r.points) {float_arr.push_back(point.at(0));float_arr.push_back(point.at(1));}// add rec word idxfor (int index : r.word_index) {float_arr.push_back(index);}// add cls resultfloat_arr.push_back(r.cls_label);float_arr.push_back(r.cls_score);}return cpp_array_to_jfloatarray(env, float_arr.data(), float_arr.size());
}

运行结果

http://www.xdnf.cn/news/10243.html

相关文章:

  • 考研单词笔记 2025.04.18
  • 【2025-泛计算机类-保研/考研经验帖征集】
  • 考研408第一章计算机系统概述——1.1-1.2操作系统的基本概念与发展历程
  • 详解STM32时基单元中参数 TIM_ClockDivision 的含义
  • 再看开源多模态RAG的视觉文档(OCR-Free)检索增强生成方案-VDocRAG
  • clickhouse数据导出导入
  • Spring Boot资源耗尽问题排查与优化
  • 大语言模型的训练、微调及压缩技术
  • 大语言模型减少幻觉的常见方案
  • 软件开发中的入静与禅定:探寻深度专注与灵感的源泉
  • 树莓派练习
  • 黑马点评:附近商铺+用户签到+UV统计【学习笔记】
  • OrangePi 5 Pro vs OrangePi AI Pro 详细对比分析
  • 7、生命周期:魔法的呼吸节奏——React 19 新版钩子
  • 免费将静态网站部署到服务器方法(仅支持HTML,CSS,JS)
  • hadoop的三大结构及其各自的作用
  • 基于尚硅谷FreeRTOS视频笔记——6—滴答时钟—上下文切换
  • ubuntu 22.04 使用ssh-keygen创建ssh互信账户
  • OpenGauss 数据库介绍
  • AI 编程工具—如何在 Cursor 中集成使用 MCP工具
  • 基于大模型的直肠息肉诊疗全流程风险预测与方案优化研究报告
  • 深入 MySQL 高级查询:JOIN、子查询与窗口函数的实用指南
  • ARM寄存器组织
  • 51c嵌入式~单片机~合集5~DMA
  • 数据可视化笔记:柱状图
  • 【Java报错】数据库查询报错this is incompatible with sql_mode=only_full_group_by
  • MAC-如果是分页查询,怎么分批次in;基于多线程的分页查询工具类
  • 492Q 型气缸盖双端面铣削组合铣床总体设计
  • Jenkins 多分支流水线: 如何创建用于 Jenkins 状态检查的 GitHub 应用
  • vue3学习笔记之条件渲染