• Android 在自己的项目中接入OpenCV+YOLOv8+NCNN : 实现人像分割


    1. 前言

    通过前两篇文章 Android 导入ncnn-android-yolov8-seg : 实现人体识别和人像分割Android ncnn-android-yolov8-seg源码解析 : 实现人像分割 ,我们已经跑起来了程序,也分析了其源码。
    接下来,这篇文章我们来实战一下,抽取出Demo的核心代码,在自己的项目中,使用Java层的Camera API,在JNI层使用OpenCV+YOLOv8+NCNN,来实现人体识别和人像分割功能。

    实现效果如下,整个图像的是相机的原图,左上角部分,是我们进行人像识别、人像分割后,处理得到的图像 (未做镜像处理,所以暂时和原图左右是相反的)

    在这里插入图片描述

    >>> 本文的源码demo可以直接看这里 :
    Android 基于 OpenCV+YOLOv8+NCNN 实现人像分割 Demo 源码下载

    2. 新建项目

    2.1 新建主项目

    在这里插入图片描述

    2.2 新建 Native library

    在这里插入图片描述

    2.3 在app中添加MyNcnnLib依赖

    implementation(project(mapOf("path" to ":MyNcnnLib")))
    
    • 1

    2.4 配置NDK版本

    记得在项目根目录下的local.properties中,配置NDK版本,这里的NDK版本需要在NDK16-NDK20之间

    # 这里的路径需修改为你电脑中ndk的具体路径
    ndk.dir=C\:\\Developer\\Android_SDK\\ndk\\20.0.5594570
    
    • 1
    • 2

    3. 接入OpenCV+YOLOv8+NCNN

    3.1 导入NCNN和OpenCV

    我们将ncnn-20221128-android-vulkanopencv-mobile-4.6.0-android复制到cpp文件夹下

    在这里插入图片描述

    3.2 复制cpp文件

    yolo.cppyolo.h复制到cpp文件夹下
    在这里插入图片描述

    3.3 配置Cmake

    新版Android StudioCMakeLists.txt的位置和Android Studio 3.6CMakeLists.txt的路径位置不一样,所以CMakeLists.txt在设置配置的时候,设置的路径也是不一样的。

    初始的CMakeLists.txt

    cmake_minimum_required(VERSION 3.22.1)
    
    
    project("myncnnlib")
    
    
    add_library(${
       CMAKE_PROJECT_NAME} SHARED
            myncnnlib.cpp)
    
    target_link_libraries(${
       CMAKE_PROJECT_NAME}
            android
            log)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    配置后的CMakeLists.txt

    cmake_minimum_required(VERSION 3.22.1)
    
    project("myncnnlib")
    
    set(OpenCV_DIR ${
       CMAKE_SOURCE_DIR}/opencv-mobile-4.6.0-android/sdk/native/jni)
    
    find_package(OpenCV REQUIRED core imgproc)
    
    set(ncnn_DIR ${
       CMAKE_SOURCE_DIR}/ncnn-20221128-android-vulkan/${
       ANDROID_ABI}/lib/cmake/ncnn)
    
    find_package(ncnn REQUIRED)
    
    add_library(${
       CMAKE_PROJECT_NAME} SHARED
            myncnnlib.cpp
            yolo.cpp)
    
    target_link_libraries(${
       CMAKE_PROJECT_NAME}
            ncnn
            camera2ndk
            mediandk
            ${
       OpenCV_LIBS}
            android
            log)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    4. 创建JNI接口

    4.1 新建JNI接口

    NcnnNativeLib.kt中,新增两个JNI方法

    /**
     * 初始化NCNN
     *
     * @return 是否成功
     */
    external fun load(mgr: AssetManager, modelid: Int, cpugpu: Int): Boolean
    
    /**
     * 人像检测
     *
     */
    external fun detect(data: ByteArray?, width: Int, height: Int, cameraId: Int): ByteArray
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4.2 cpp中增加对应JNIf方法

    myncnnlib.cpp中,增加对应的JIN方法

    extern "C"
    JNIEXPORT jboolean JNICALL
    Java_com_heiko_myncnnlib_NativeLib_load(JNIEnv *env, jobject thiz, jobject assetManager,
                                            jint modelid, jint cpugpu) {
       
    
    }
    extern "C"
    JNIEXPORT jbyteArray JNICALL
    Java_com_heiko_myncnnlib_NativeLib_detect(JNIEnv *env, jobject thiz, jbyteArray data_,
                                              jint w, jint h, jint camera_id) {
       
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.3 声明include

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include "opencv2/opencv.hpp"
    #include 
    #include 
    #include "yolo.h"
    
    static Yolo *g_yolo = 0;
    static ncnn::Mutex lock;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4.4 加载模型

    这里将Demo中的loadModel中的代码,全部拷贝过来

    extern "C"
    JNIEXPORT jboolean JNICALL
    Java_com_heiko_myncnnlib_NativeLib_load(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[] =
                {
       
                        "n",
                        "s",
                };
    
        const int target_sizes[] 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    苹果认证Apple Store Connenct api的使用
    每日刷题打卡Day14
    Android 14 权限
    浅谈分布式任务调度系统Celery的设计与实现
    思腾云计算
    新闻资讯|基于微信小程序的经济新闻资讯系统设计与实现(源码+数据库+文档)
    【VSCode】VSCode自定义代码编辑区背景色
    【神经网络】【VggNet】
    点云端面转换为2D平面图
    Spring Boot与Kubernetes结合:构建高可靠、高性能的微服务架构
  • 原文地址:https://blog.csdn.net/EthanCo/article/details/133615951