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

本文讲述了作者在开发一款盲人阅读辅助APP时,如何部署并行运行YoloV8和MediapipeHand的ncnn模型,解决技术挑战,包括模型整合、并发控制和资源管理,以实现实时无干扰的多模型推理。
摘要由CSDN通过智能技术生成

在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
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值