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")))

2.4 配置NDK版本

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

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

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)

配置后的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)

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

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) {
   
    
    

}

4.3 声明include

#include <jni.h>
#include <string>
#include <platform.h>
#include <benchmark.h>
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include "opencv2/opencv.hpp"
#include <string>
#include <iostream>
#include "yolo.h"

static Yolo *g_yolo = 0;
static ncnn::Mutex lock;

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[] 

猜你喜欢

转载自blog.csdn.net/EthanCo/article/details/133615951