android 实现算法模型部署方案

注:此次记录和梳理android AI 算法模型部署和实现的流程,包含算法部署、从andorid 前段获取bitmap数据进行输入,结果展示和算法so打包和交付流程进行介绍

一:流程:

     如果我们训练一个cnn 模型,怎样才能将模型实现在android 平台上运行,并实现结果展示呢?本文章流程主要介绍比如分类、检测、分割等算法训练的pytorch(x.pt)模型,实现在android 上运行并将结果返回在前段界面上进行展示(便于我们测试结果),最终将我们的算法推理代码封装起来,提供给前段android 应用的同事进行扩展产品开发的方案。

     一般我们实现简单的算法推理部署可能做到将x.pt 模型转换到对象平台支持的框架即可,再或者是将python 推理代码转换为x.cpp/x.h 的样例给其他人员即可,目前由于算法卷的厉害,还是探索下算法部署和应用流程哈。以下是以android 上部署算法为例需要考虑的几个方面:

     1).算法模型部署方案选择

     2).算法接口和java如何交互实现

      3).算法模型输入如何导入

      4).算法模型输出如何展示

      5).算法工程如何仅通过给其他开发人员二次开发

1.1 算法模型部署方案选择

      目前android 上部署算法模型,需要考虑支持的推理算法框架,常用的有:ncnn、tnn、mnn、tflite、rknn(存在硬件限制)等。以上框架都需要考虑将python 训练的模型转换为对象框架的模型,有可直接转换、有存在以onnx 为桥梁的转换方案,具体看框架支持的op 情况和是否调用开源模型直接使用。

        现阶段大多数使用者还是基于不同训练框架先转换到onnx再转到对象平台,因本次介绍以人脸识别、paddleocr 模型 为例,所以流程上选择为onnx 为桥梁到ncnn,工作中有时会兼容很多对象平台(瑞芯微、英伟达、海思、服务端)所以建议训练的模型转换到onnx 备着方便些。

       部署android 端,目前我所接触的部署硬件为:纯cpu 版本的系统和支持rknn的瑞芯微系列硬件平台,本次以通用cpu 部署进行介绍。

        在android 系统平台实现算法部署推理,我们要结合ncnn 框架实现,需要准备编译ncnn 库,使用生成的转换脚本、量化脚本、模型加密等,pt 模型我们要在python 代码中调用torch.onnx.export(目前参考很多,或者chatgpt一建帮忙,这里推荐贴个镜像地址方便秩咨询:https://www.aichatgpt5.com/),然后将onnx 模型调用onnx2ncnn 进行转换,这里要注意,有时候保存的模型可能存在很多冗余的op分支,可用onnxsimper 库进行裁剪下再转换。

2. 算法接口和java如何交互实现

     JNI接口:通常我们将训练的.pt模型转换为可部署的模型ncnn模型为例,需要将算法推理部分以c/c++ 的形式写出模型初始化,模型推理的代码函数。但是对于这种c部分的代码,java端无法直接调用,因此需要包装成jni 接口提供给java调用。jni 接口疯转c++实现需要坐native的实现。、

(1).在java 层定义jni 接口,有固定的格式,以实现一个导入路径给c++ 的函数,在java层的实现如下:

package  com.project.youfile; 

public static native void pathString(String rootPath);
public class jnitest
{
    public static native void pathString(String rootPath);
    
    static {
        System.loadLibrary("libxxxaaa");
    }
}

    其中public static native void pathString(String rootPath); 就是一个jni接口;

(2):如何在c++中实现:

        a.首先需在build.gadle 配置sdk,ndk(具体版本需要根据可根据添加的第三方库统一)以及需要编译c的camke

        添加cmake 为例:

    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }

      b.建立文件夹:创建c++ 的相关代码和工程目录,将c相关的代码和依赖放置在其中,并在cmakelist.txt 中添加相关编译。

      b.nativate.cpp 中实现:再创建一个native.cpp 函数,作为调用自行编译的函数,在封装native接口:以上面的pathString 接口为例:

#include <jni.h>
#include <string>
#include <iostream>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
using  namespace std;

string root_path ="";
JNIEXPORT void JNICALL Java_com_project_youfile_你接口的java类名_rootpathSet(
        JNIEnv *env, jclass clazz, jstring _root_path) {
    const char *str = env->GetStringUTFChars(_root_path, NULL);
    root_path = str;
    env->ReleaseStringUTFChars(_root_path, str);
}

      以上就创建一个jni接口,作用是将java 的string  传递给c使用;

       

更新中。。。。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值