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类中:

java 复制代码
    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的处理逻辑及返回结果都在这里了。

cpp 复制代码
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 point
    for (const std::vector<int> &point : r.points) {
      float_arr.push_back(point.at(0));
      float_arr.push_back(point.at(1));
    }
    // add rec word idx
    for (int index : r.word_index) {
      float_arr.push_back(index);
    }
    // add cls result
    float_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());
}

运行结果

相关推荐
行墨37 分钟前
CoordinatorLayout基本使用与分析<二>
android
行墨1 小时前
CoordinatorLayout基本使用与分析<一>
android
tracyZhang2 小时前
Android低版本bitmap native分配实现原理
android·性能优化
奥尔特星云大使13 小时前
MySQL 慢查询日志slow query log
android·数据库·mysql·adb·慢日志·slow query log
2501_9159184117 小时前
iOS 框架全解析,原生框架与跨平台框架对比、开发应用打包与 App Store 上架实战经验
android·ios·小程序·https·uni-app·iphone·webview
K24B;17 小时前
多模态大语言模型LISA++
android·人工智能·语言模型·分割·多模态大语言模型
AI人工智能+19 小时前
表格识别技术:突破传统OCR的局限,通过定位-解析-重建三步策略攻克无边框、合并单元格等视觉难题
人工智能·深度学习·ocr·表格识别
molihuan1 天前
开源 全平台 哔哩哔哩缓存视频合并 Github地址:https://github.com/molihuan/hlbmerge_flutter
android·flutter·缓存·ffmpeg·开源·github·音视频