安卓平台darknet转ncnn【完整编译流程】

这里采用的是官方推荐的darknet2ncnn的方案

darknet2ncnn库链接:https://github.com/xiangweizeng/darknet2ncnn ,感谢作者在我编译过程中给我的帮助。
我是依次将darknet库编译成安卓平台的静态库,ncnn库编译成安卓平台的静态库(也可以不用自己编译,官方有现成的编译结果),然后再编译成darknet2ncnn静态库,最后在参考darknet2ncnn给的例子的yolov2.cpp文件来编写自己的JNI接口。

一、darknet安卓平台的编译

首先在/src/main目录下新建cpp文件夹,将darknet待编译的文件放入其中:
在这里插入图片描述

配置build.gradle文件:

配置静态库编译信息
指定Cmakelists文件的路径以及指定待编译文件的路径
Cmakelists.txt文件的配置:
   设置头文件目录

include_directories(
       ../cpp
       src/main/cpp/src/
       ../cpp/include
)

   将待编译的源文件生成链接文件

file(GLOB darknet_files "${CMAKE_SOURCE_DIR}/src/main/cpp/src/*.c")
set(DARKNET_SRC_LISTS
       ${darknet_files}
       )

add_library( # Sets the name of the library.
       darknet
       STATIC
       # Sets the library as a shared library.
       ${DARKNET_SRC_LISTS}
       )
    将目标文件与库文件进行链接
target_link_libraries( # Specifies the target library.
                     darknet

                      # Links the target library to the log library
                      # included in the NDK.
                      ${log-lib} )

编译生成静态库:
   通过AS平台的编译该模块,在app/build/intermediates/cmake/debug/obj/目录下获取libdarknet.a;
在这里插入图片描述

二、ncnn安卓平台的编译

可以参照darknet的编译方式获取libncnn.a,当然也可以去官方下载编译的库:
  链接是:https://github.com/Tencent/ncnn/releases

三、darknet2ncnn安卓平台的编译

首先将darknet2ncnn库待编译的C文件和ncnn库的头文件放入cpp目录下:
在这里插入图片描述
在src/main/目录下新建jniLibs文件,将之前编译出的armeabi-v7a架构的静态库添加进去
在这里插入图片描述
配置build.gradle文件:
配置静态库编译信息:
在这里插入图片描述
配置Cmakelists.txt文件:
   设置头文件目录

   include_directories(src/main/cpp/layer)
   include_directories(src/main/cpp/include)
   include_directories(src/main/cpp)

   设置静态库的路径

set(ncnn_src ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})
add_library (ncnn_lib STATIC IMPORTED)
set_target_properties(ncnn_lib PROPERTIES IMPORTED_LOCATION ${ncnn_src}/libncnn.a)
add_library (darknet_lib STATIC IMPORTED)
set_target_properties(darknet_lib PROPERTIES IMPORTED_LOCATION ${ncnn_src}/libdarknet.a)

   将待编译的源文件生成链接文件

set(DARKNET_SRC_LISTS
       src/main/cpp/layer/darknet_activation.cpp
       src/main/cpp/layer/darknet_shortcut.cpp
       src/main/cpp/layer/yolov1_detection.cpp
       src/main/cpp/layer/yolov3_detection.cpp
       src/main/cpp/object_detection.cpp
       src/main/cpp/register_darknet.cpp
       src/main/cpp/darknet2ncnn.cpp
       )
add_library( # Sets the name of the library.
       darknet2ncnn
       STATIC
       # Sets the library as a shared library.
       ${DARKNET_SRC_LISTS}
       )

    将ncnn库link到darknet2ncnn

target_link_libraries( # Specifies the target library.
                     darknet2ncnn
                     ncnn_lib
                     darknet_lib
                     # Links the target library to the log library
                     # included in the NDK.
                     ${log-lib}
      )

最终编译在app/build/intermediates/cmake/debug/obj/目录生成libdarknet2ncnn.a

四、安卓端调用darknet2ncnn的接口进行初始化,加载模型

将上面编译出的静态库放入/src/mian/jniLibs/armeabi-v7a目录下,将对应的头文件放入src/main/cpp目录下:
在这里插入图片描述
配置build.gradle文件:
在这里插入图片描述
在这里插入图片描述
配置CmakeList.txt文件:

   include_directories(src/main/cpp/layer)
   include_directories(src/main/cpp/include)
   include_directories(src/main/cpp)


set(ncnn_src ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})

add_library (ncnn_lib STATIC IMPORTED)
set_target_properties(ncnn_lib PROPERTIES IMPORTED_LOCATION ${ncnn_src}/libncnn.a)

add_library (darknet_lib STATIC IMPORTED)
set_target_properties(darknet_lib PROPERTIES IMPORTED_LOCATION ${ncnn_src}/libdarknet.a)

add_library (ncnn2darknet_lib STATIC IMPORTED)
set_target_properties(ncnn2darknet_lib PROPERTIES IMPORTED_LOCATION ${ncnn_src}/libdarknet2ncnn.a)

add_library( # Sets the name of the library.
       yolov2_jni

       # Sets the library as a shared library.
       SHARED

       # Provides a relative path to your source file(s).
       src/main/cpp/yolov2_jni.cpp)
find_library( # Sets the name of the path variable.
             log-lib

             # Specifies the name of the NDK library that
             # you want CMake to locate.
             log )
target_link_libraries( # Specifies the target library.
       yolov2_jni2

                      ncnn2darknet_lib
                      darknet_lib
                      ncnn_lib
                      jnigraphics
               
                      # Links the target library to the log library
                      # included in the NDK.
                      ${log-lib} )

编写jni接口的cpp文件:


#include <android/bitmap.h>
#include <android/log.h>
#include <jni.h>
#include <string>
#include <vector>
// ncnn
#include "net.h"
#include "opencv.h"

#include <sys/time.h>
#include <unistd.h>
#include "net.h"
#include "darknet2ncnn.h"
#include "input.h"
#include "ncnn_tools.h"
#include "benchmark.h"

static ncnn::UnlockedPoolAllocator g_blob_pool_allocator;
static ncnn::PoolAllocator g_workspace_pool_allocator;

static ncnn::Mat ncnn_param;
static ncnn::Mat ncnn_bin;
static ncnn::Net ncnn_net;
static ncnn::Net ncnn_h;
CustomizedNet yolo;
extern "C" {
JNIEXPORT jboolean JNICALL
Java_com_rocky_ImgIden_utils_JNIUtil_Init(JNIEnv *env, jobject obj,
                                                       jbyteArray param, jbyteArray bin) {
   
   register_darknet_layer(yolo);
   //init param
   {
       int len = env->GetArrayLength(param);
       ncnn_param.create(len, (size_t) 1u);
       env->GetByteArrayRegion(param, 0, len, (jbyte *) ncnn_param);

//        int ret = ncnn_net.load_param((const unsigned char *) ncnn_param);
       int ret =   yolo.load_param_mem( ncnn_param);ret, len);
   }
   //init bin
   {
       int len = env->GetArrayLength(bin);
       ncnn_bin.create(len, (size_t) 1u);
       env->GetByteArrayRegion(bin, 0, len, (jbyte *) ncnn_bin);
//        ncnn_h.use_winograd_convolution=0;
//        ncnn_h.use_sgemm_convolution=0;
//        ncnn_net.use_winograd_convolution=0;
//        ncnn_net.use_sgemm_convolution=0;
       int ret =   yolo.load_model((const unsigned char *) ncnn_bin);

   }

//    ncnn::Option opt;
//    opt.lightmode = true;
//    opt.num_threads = 2;//线程数
//    opt.blob_allocator = &g_blob_pool_allocator;
//    opt.workspace_allocator = &g_workspace_pool_allocator;
//    ncnn::set_default_option(opt);

   return JNI_TRUE;
}

// public native String Detect(Bitmap bitmap);
JNIEXPORT jfloatArray JNICALL
Java_com_rocky_ImgIden_utils_JNIUtil_Detect (JNIEnv *env, jobject thiz,
                                                         jobject bitmap) {
   // ncnn from bitmap
   ncnn::Mat in;
   {

       AndroidBitmapInfo info;
       AndroidBitmap_getInfo(env, bitmap, &info);
       //        int origin_w = info.width;
       //        int origin_h = info.height;
       //        int width = 416;
       //        int height = 416;
       int width = info.width;
       int height = info.height;
       if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
           return NULL;
       void *indata;
       AndroidBitmap_lockPixels(env, bitmap, &indata);
       // 把像素转换成data,并指定通道顺序
       //        in = ncnn::Mat::from_pixels_resize((const unsigned char*)indata, ncnn::Mat::PIXEL_RGBA2RGB, origin_w, origin_h, width, height);

       in = ncnn::Mat::from_pixels((const unsigned char *) indata, ncnn::Mat::PIXEL_RGBA2RGB,
                                   width, height);

       AndroidBitmap_unlockPixels(env, bitmap);
   }
   // ncnn_net
   std::vector<float> cls_scores;
   {
       // 减去均值和乘上比例
       // 减去均值和乘上比例
       const float mean_vals[3] = {0.5f, 0.5f, 0.5f};
       const float scale[3] = {1.0/255, 1.0/255, 1.0/255};
       in.substract_mean_normalize(0, scale);

       ncnn::Extractor ex = yolo.create_extractor();
       // 如果时不加密是使用ex.input("data", in);
       //        ex.input(mobilenet_v2_param_id::BLOB_data, in);
       ex.input(0, in);
       //ex.input("data",in);
       ncnn::Mat out;
       ncnn::Blob *out_blob = yolo.get_last_layer_output_blob();
       int result = ex.extract(out_blob->name.c_str(), out);
       if (result != 0)
       {
           printf("ncnn error: %d\n", result);
           return reinterpret_cast<jfloatArray>(result);
       }
       // 如果时不加密是使用ex.extract("prob", out);
       //ex.extract(mobilenet_v2_param_id::BLOB_prob, out);
//        ex.extract(40, out);
       //        ex.extract("detection-out",out);
       //        int output_wsize = in.w;
       //        int output_hsize = in.h;
       //        jint *in_out[output_wsize * output_hsize * in.c];
       //        for(int i=0; i<output_wsize * output_hsize * in.c;i++){
       //            in_out[i] = (int *)&in[i];
       //        }
       //        jintArray  jOutImData = env->NewIntArray(output_hsize * output_wsize * in.c);
       //        env->SetIntArrayRegion(jOutImData, 0, output_hsize * output_wsize * in.c, reinterpret_cast<const jint *>(*in_out));
       int output_wsize = out.w;
       int output_hsize = out.h;

       jfloat *output[output_wsize * output_hsize];
       for (int i = 0; i < out.h; i++) {
           for (int j = 0; j < out.w; j++) {
               output[i * output_wsize + j] = &out.row(i)[j];
           }
       }
       jfloatArray jOutputData = env->NewFloatArray( output_wsize * output_hsize);
       if (jOutputData == nullptr) return nullptr;
       env->SetFloatArrayRegion(jOutputData, 0, output_wsize * output_hsize,
                                reinterpret_cast<const jfloat *>(*output));  // copy

       return jOutputData;

   }
}
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值