在Android端实现多个ncnn模型部署并实现并行推理

在Android端实现多个ncnn模型部署并实现并行推理

本次基于个人开发的盲图AI——辅助盲人阅读的智能APP项目的需求来实现,一开始遇到了非常多的技术瓶颈,例如模型部署,识别,绘制等,遇到了各种各样的技术壁垒,都是从零基础开始学起。以下介绍这次开发中所学到的关键技术点。

img

(1)部署yolo ncnn与mediapipe hand ncnn模型并实现同时推理

相信大家在做人工智能方向的app的时候都会遇到一个模型无法满足需求的时候吧?今天我来聊聊如何在一个app里面,整合两个ncnn模型并让他们实现同时运作并且互不干扰。

首先你得学会如何在移动端部署ncnn模型,具体看我另外一篇文章:关于ncnn模型在移动端的部署

其实部署两个Ncnn模型,无非就是两个Ncnn:Net,也就是说你需要在cpp层里面创建两个Net对象,后续就是持有这两个对象去做事情。首先创建两个Net对象,后创建2个集合 , 分别接受各自的返回结果 , 写2个布尔值变量分别弄2个锁 get和set都有共用各自的锁 , 各自管理自己得布尔值变量 , 2个yolo分别管理各自的布尔值 , 1个用于你第1个yolo 当返回了结果这个布尔值变量就为true 返回结果的时候判断一下这个布尔值变量是否为true , true就不重新返回结果, 另外一个用于你第2个yolo返回同理 , 开第三个线程 , 实时轮训这两个布尔值变量 , 两个都是true 就用这两个结果开始做你要做的事情 , 做完了 用第三个线程将这2个布尔值变量set成false , 就可以2个yolo各自推理自己得互不干扰 , 第三个线程也做自己得事情不干扰。(第三个线程是否创建看自己项目的需求)以下以yolo模型和MediepipeHand模型为例.

我直接把官方yolov8-ncnn的demo例子拿来改了,所以直接在yolo原来的c++文件上面融合代码。下面是JNI目录里面的代码文件

在这里插入图片描述

首先直接在主逻辑类里面更改:yolov8ncnn.cpp

第一步,创建两个Net对象和两个锁。(g_yolo原来就有的,所以只需要再创建一个g_hand就行)

//创建2个对象
static Yolo* g_yolo = 0;
static ncnn::Mutex lock;

static Hand* g_hand = 0;
static ncnn::Mutex lock2;

第二步,在 MyNdkCamera::on_image_render(cv::Mat& rgb) 方法里面增加用g_hand对象调用draw函数和detect函数的方法,如下:

  //hand对象
          {
                ncnn::MutexLockGuard g(lock2);
                if (g_hand)
                {
                    std::vector<PalmObject> objects;
                    g_hand->detect(rgb, objects);
                    g_hand->draw(rgb, objects);
                }
                else
                {
                    draw_unsupported(rgb);
                }

        }

第三步,在 JNI_OnUnload 方法里面增加对g_hand对象释放资源的方法

   {
        ncnn::MutexLockGuard g(lock2);
        delete g_hand;
        g_hand = 0;
    }

第四步,在JAVA层增加一个loadModel函数,yolo有自己的loadmodel函数,因此hand也需要

在这里插入图片描述

第五步,接下来就是在C++层去实现这个loadmodel2函数了,其实大部分代码都跟yolo一样,但是要注意JNI函数的命名,要改为当前项目名

JNIEXPORT jboolean JNICALL Java_com_tencent_yolov8ncnn_Yolov8Ncnn_loadModel2(JNIEnv* env, jobject thiz, jobject assetManager, jint modelid, jint cpugpu)
{
    if (modelid < 0 || modelid > 6 || cpugpu < 0 || cpugpu > 1)
    {
        return JNI_FALSE;
    }

    AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);

    __android_log_print(ANDROID_LOG_DEBUG, "ncnn", "loadModel %p", mgr);

    const char* modeltypes[] =
    {
//选择模型
        "palm-lite"
    };

    const int target_sizes[] =
    {
        192,
        192
    };

    const float mean_vals[][3] =
    {
        {0.f,0.f,0.f},
        {0.f,0.f,0.f},
    };

    const float norm_vals[][3] =
    {
        {1 / 255.f, 1 / 255.f, 1 / 255.f},
        {1 / 255.f, 1 / 255.f, 1 / 255.f},
    };

    const char* modeltype = modeltypes[(int)modelid];
    int target_size = target_sizes[(int)modelid];
    bool use_gpu = (int)cpugpu == 1;

    // reload
    {
        ncnn::MutexLockGuard g(lock2);

        if (use_gpu && ncnn::get_gpu_count() == 0)
        {
            // no gpu
            delete g_hand;
            g_hand = 0;
        }
        else
        {
            //调用load函数
            if (!g_hand)
                g_hand = new Hand;
            g_hand->load(mgr, modeltype, target_size, mean_vals[(int)modelid], norm_vals[(int)modelid], use_gpu);
        }
    }

    return JNI_TRUE;
}

第六步,到了这里其实主类修改已经完成了,但是我们的g_hand对象还要用到别的类,因此要在yolov8ncnn类的头文件引入hand.cpp

在这里插入图片描述

并且除了hand.h,其余的cpp文件也要引入到本项目的JNI目录下,即hand.cpp、hand.h、landmark.cpp、landmark.h,而在原本hand项目里面的主类则不需要引入,因为你已经把主类的逻辑都写在yolov8ncnn.cpp里面了不是吗?

第七步,引入模型文件到assets文件夹里面

在这里插入图片描述

最后一步,就是在安卓里面调用loadmodel函数了

 private void reload()
    {
        boolean ret_init = yolov8ncnn.loadModel(getAssets(), current_model, current_cpugpu);
        boolean ret_init2 = yolov8ncnn.loadModel2(getAssets(), current_model, current_cpugpu);

        if (!ret_init)
        {
            Log.e("MainActivity", "yolov8ncnn loadModel failed");
        }

        if (!ret_init2)
        {
            Log.e("MainActivity", "yolov8ncnn loadModel2 failed");
        }
    }

至此,就已经实现了两个ncnn模型的部署,其实从设计规范来说,将他们封装成一个类来进行操作是更加方便的,具体就看自己的需求啦。部署三个,四个模型也是一样的道理,但是前提得你手机cpu吃的消噢,下一篇我会讲讲如何优化多个ncnn模型部署时候的运行速度,让你的视频流不会太卡。

  • 25
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
对于MobileUNet在NCNN部署,你可以按照以下步骤进行操作: 1. 首先,你需要获取MobileUNet的模型文件和权重参数。这些文件通常是在训练过程中生成的,你可以从相关资源库或者官方文档中获取。 2. 下载并配置NCNN库。NCNN是一个轻量级的神经网络计算库,适用于移动设备和嵌入式系统。你可以从NCNN的官方GitHub仓库下载源代码,并按照其文档进行配置和编译。 3. 在你的项目中使用NCNN库。将NCNN库导入到你的项目中,并确保你的项目能够正确地链接和使用NCNN库的功能。 4. 加载MobileUNet模型。使用NCNN提供的接口,你可以加载MobileUNet模型文件和权重参数。具体的加载代码可能会有所不同,具体取决于你选择的编程语言和平台。 5. 对输入图像进行预处理。在将图像输入到MobileUNet模型之前,你可能需要对图像进行一些预处理,例如调整大小、归一化或裁剪等操作。确保预处理过程与MobileUNet模型训练时使用的预处理过程一致。 6. 运行推理。使用NCNN提供的接口,将预处理后的图像输入MobileUNet模型,然后运行推理过程。推理过程将产生预测结果,即MobileUNet对输入图像的分割结果。 7. 后处理和可视化。根据你的需求,你可以对模型的输出进行后处理,例如阈值化、后处理滤波或对象边界框绘制等操作。最后,你可以将结果可视化或保存到文件中。 以上是MobileUNet在NCNN部署步骤的一个大致指导,具体细节可能因为你的应用场景和需求而有所不同。在实际操作中,你可能需要参考NCNN的文档和示例代码来更好地理解和应用该库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值