Android工程中使用ncnn进行yolo识别

参考资料:https://github.com/FeiGeChuanShu/ncnn-android-yolov8/tree/main/ncnn-android-yolov8

将ncnn-android-yolov8称为A工程,我自己的工程称为B工程

1.下载ncnn-android-yolov8工程,将A中的ncnn-20230223-android-vulkan、yolo.h、yolo.cpp放入B的app/src/main/cpp/目录下。这里用不到摄像头,去掉ndkcamera.h、ndkcamera.cpp。yolov8ncnn.cpp是JNI接口文件,B中已经有了,否则会冲突。

2.将A的Assets目录yolov8n.bin、yolov8n.param、yolov8s.bin、yolov8s.param,复制到B的app/src/main/

3.修改CMakeList.txt,包括了ffmpeg、opencv、ncnn,如果用不上可删除一部分

注意,ffmpeg放到app/src/main/cpp/目录下

cpp 复制代码
cmake_minimum_required(VERSION 3.10)
project("rtspplayerforandroid")

# 【第一块】全局编译标准、OpenMP 放最顶部
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(OpenMP REQUIRED)
if(OpenMP_FOUND)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS} -static-openmp")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} -static-openmp")
endif()

# 【第二块】NCNN 先配置,提前加入头文件路径(关键修复)
set(ncnn_DIR ${CMAKE_SOURCE_DIR}/ncnn-20230223-android-vulkan/${ANDROID_ABI}/lib/cmake/ncnn)
find_package(ncnn REQUIRED)
# ncnn头文件路径提前加入,编译源码时就能搜到platform.h/net.h/mat.h
include_directories(${ncnn_INCLUDE_DIRS})

# 【第三块】OpenCV配置
set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/opencv-mobile-4.6.0-android/sdk/native/jni)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

# 【第四块】FFmpeg 预编译库 + 头文件
set(JNI_LIBS_DIR ${CMAKE_SOURCE_DIR}/ffmpeg)
include_directories(${JNI_LIBS_DIR}/${ANDROID_ABI}/include)

add_library(avutil SHARED IMPORTED)
set_target_properties(avutil PROPERTIES IMPORTED_LOCATION ${JNI_LIBS_DIR}/${ANDROID_ABI}/lib/libavutil.so )
add_library(swresample SHARED IMPORTED )
set_target_properties(swresample PROPERTIES IMPORTED_LOCATION ${JNI_LIBS_DIR}/${ANDROID_ABI}/lib/libswresample.so )
add_library(swscale SHARED IMPORTED )
set_target_properties(swscale PROPERTIES IMPORTED_LOCATION ${JNI_LIBS_DIR}/${ANDROID_ABI}/lib/libswscale.so )
add_library(avcodec SHARED IMPORTED )
set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${JNI_LIBS_DIR}/${ANDROID_ABI}/lib/libavcodec.so )
add_library(avformat SHARED IMPORTED )
set_target_properties(avformat PROPERTIES IMPORTED_LOCATION ${JNI_LIBS_DIR}/${ANDROID_ABI}/lib/libavformat.so )
add_library(avfilter SHARED IMPORTED )
set_target_properties(avfilter PROPERTIES IMPORTED_LOCATION ${JNI_LIBS_DIR}/${ANDROID_ABI}/lib/libavfilter.so )
# avdevice 如果你没用到可以注释,避免路径不存在报错
# add_library(avdevice SHARED IMPORTED )
# set_target_properties(avdevice PROPERTIES IMPORTED_LOCATION ${JNI_LIBS_DIR}/${ANDROID_ABI}/lib/libavdevice.so )

# 【第五块】现在才创建主库(此时所有头文件路径全部加载完毕)
add_library(
        rtspplayerforandroid
        SHARED
        native-lib.cpp
        CustomPlayer.cpp
        yolo.cpp
)

# 【第六块】系统日志库
find_library(log-lib log)

# 【第七块】统一链接所有依赖(补齐所有ffmpeg库)
target_link_libraries(
        rtspplayerforandroid
        avutil
        swresample
        swscale
        avcodec
        avformat
        avfilter
        # avdevice
        ncnn
        ${OpenCV_LIBS}
        OpenMP::OpenMP_CXX
        android
        mediandk
        ${log-lib}
)

4.添加接口loadModel,加载模型

复制代码
public native boolean loadModel(AssetManager mgr, int modelid, int cpugpu);
cpp 复制代码
#include <android/asset_manager_jni.h>
#include <android/native_window_jni.h>
#include <android/native_window.h>

#include <android/bitmap.h>
#include <android/log.h>

#include <jni.h>

#include <string>
#include <vector>

#include <platform.h>
#include <benchmark.h>

#include "yolo.h"
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

#if __ARM_NEON
#include <arm_neon.h>
#endif // __ARM_NEON

......

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

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_skydroid_rcsdkdemo_MyPlayer_loadModel(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[] =
            {
                    320,
                    320,
            };

    const float mean_vals[][3] =
            {
                    {103.53f, 116.28f, 123.675f},
                    {103.53f, 116.28f, 123.675f},
            };

    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(lock);

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

    return JNI_TRUE;
}

在JNI_OnUnload添加

cpp 复制代码
	{
		ncnn::MutexLockGuard g(lock);

		delete g_yolo;
		g_yolo = 0;
	}

5.Java加载模型

cpp 复制代码
myPlayer = new MyPlayer();
myPlayer.loadModel(getAssets(),0,0);

6.在CustomPlayer.cpp加入识别代码

注意yolo.detect默认mat为rgb,如果是RGBA格式,需要修改yolo.detect函数

cpp 复制代码
#include "yolo.h"

extern Yolo* g_yolo;
extern ncnn::Mutex lock;

......
 if (g_yolo)
{
    std::vector<Object> objects;
    g_yolo->detect(mat, objects, 0.25f, 0.45f);
    g_yolo->draw(mat, objects);
}

将ncnn::Mat::PIXEL_RGB2BGR改为ncnn::Mat::PIXEL_RGBA2BGR

相关推荐
solo_9910 小时前
用 LSPosed 模拟录屏音频编码器卡顿:从思路到落地
android
zzq779711 小时前
别把大模型 API Key 写进 APK:移动 AI 应用接口防盗刷实践
android·人工智能·安全·app加固·御盾安全·安卓加固
xiaopang12 小时前
RK3568 AOSP 编译与快速部署实战
android
码农coding13 小时前
android12 SystemUI之通知
android
summerkissyou198714 小时前
android - 性能 - Perfetto - cpu 分析教程及例子
android·性能
AFinalStone16 小时前
Android 7系统休眠唤醒(七)内核层—wakelock与autosleep机制
android·休眠唤醒
starvapour16 小时前
在关机键损坏的情况下让手机关机
android·adb·手机
AFinalStone16 小时前
Android 7系统休眠唤醒(八)内核层—Alarm定时唤醒与硬件唤醒源
android·电源管理·休眠唤醒