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

发布时间:2026/7/29 11:49:27

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/目录下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);#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添加{ ncnn::MutexLockGuard g(lock); delete g_yolo; g_yolo 0; }5.Java加载模型myPlayer new MyPlayer(); myPlayer.loadModel(getAssets(),0,0);6.在CustomPlayer.cpp加入识别代码注意yolo.detect默认mat为rgb如果是RGBA格式需要修改yolo.detect函数#include yolo.h extern Yolo* g_yolo; extern ncnn::Mutex lock; ...... if (g_yolo) { std::vectorObject objects; g_yolo-detect(mat, objects, 0.25f, 0.45f); g_yolo-draw(mat, objects); }将ncnn::Mat::PIXEL_RGB2BGR改为ncnn::Mat::PIXEL_RGBA2BGR

相关新闻