yolov3-tiny:Android端基于darknet2ncnn之实现二

       经过一段时间的反复摸索,终于在Android端基于darknet2ncnn的框架实现了yolov3-tiny,一张图片的检测时间为500ms以内,基本满足需求,接着分享该实现的第二部分内容,同时也欢迎大家关注我的微信公众号机器视觉交流社或个人微信号“LuckyZiXiao”进行交流。

      前提:在pc端已经编译好darknet2ncnn环境,并且将Android下需要的nccn库文件也编译好,不清楚的可以参考我之前的文章。

      新建Android工程,安装下面的步骤来

  1. 右击file---New---New Project

   2、选择Native C++

3、next,语言选择java

4、next,选择C++11

5、在工程目录main文件夹下新建assset和jniLibs两个文件夹

6、将之前编译的ncnn在Android下运行的库拷贝到jniLibs文件下

7、将转换的yolov3-tiny的网络文件和权重文件拷贝到assets文件夹下,新建words.name文件,将类名写入改文件。

8、在工程目录cpp文件夹下新建darknet、darknet2ncnn和ncnn三个文件夹,并分别将pc端darknet2ncnn下的incule和src、darknet2ncnn\darkent下的incule和src、darknet2ncnn\ncnn下的incule和src拷入对应的文件夹下。

9、在工程目录cpp文件夹下新建yolov3-tiny-jni.cpp,部分代码如下:

#include <android/bitmap.h>
#include <android/log.h>
#include <android/asset_manager_jni.h>
#include <jni.h>
#include <string>
#include <vector>

#include <sys/time.h>
#include <unistd.h>

#include <stdio.h>
#include <algorithm>
#include <fstream>

#include "darknet2ncnn.h"
#include "ncnn/src/layer/input.h"
#include "ncnn_tools.h"

extern "C" {

static CustomizedNet yolo;
static ncnn::Mat ncnn_param;
static ncnn::Mat ncnn_bin;


JNIEXPORT jboolean JNICALL
Java_com_bket_yolov3Tiny_yolov3Tiny_Init(JNIEnv *env, jobject obj, jstring param, jstring bin) {
    __android_log_print(ANDROID_LOG_DEBUG, "yolov3TinyJni", "enter the jni func");

     register_darknet_layer(yolo);

    const char *param_path = env->GetStringUTFChars( param, NULL);
    if(param_path == NULL)
        return JNI_FALSE;
    __android_log_print(ANDROID_LOG_DEBUG, "yolov3TinyJni", "load_param %s", param_path);

    //yolo.
    int ret = yolo.load_param(param_path);
    __android_log_print(ANDROID_LOG_DEBUG, "yolov3TinyJni", "load_param result %d", ret);
    env->ReleaseStringUTFChars( param, param_path);

    const char *bin_path = env->GetStringUTFChars( bin, NULL);
    if(bin_path == NULL)
        return JNI_FALSE;
    __android_log_print(ANDROID_LOG_DEBUG, "yolov3TinyJni", "load_model %s", bin_path);

    int ret2 = yolo.load_model(bin_path);
    __android_log_print(ANDROID_LOG_DEBUG, "yolov3TinyJni", "load_model result %d", ret2);
    env->ReleaseStringUTFChars( bin, bin_path);
    return JNI_TRUE;
}

JNIEXPORT jfloatArray JNICALL Java_com_bket_yolov3Tiny_yolov3Tiny_Detect(JNIEnv* env, jobject thiz, jobject bitmap)
{
    ncnn::Input *input = (ncnn::Input *)yolo.get_layer_from_name("data");

    AndroidBitmapInfo info;
    AndroidBitmap_getInfo(env, bitmap, &info);
    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);

    ncnn::Mat in = ncnn::Mat::from_pixels_resize((const unsigned char*)indata,      ncnn::Mat::PIXEL_RGBA2RGB, width, height, input->w, input->h);


    AndroidBitmap_unlockPixels(env, bitmap);

    const float norm_vals[3] = {1 / 255.0, 1 / 255.0, 1 / 255.0};
    in.substract_mean_normalize(0, norm_vals);
    ncnn::Extractor ex = yolo.create_extractor();
    ex.input("data",in);
    ex.set_light_mode(false);
    ex.set_num_threads(6);

    ncnn::Mat out;
    ncnn::Blob *out_blob = yolo.get_last_layer_output_blob();
    int result = ex.extract(out_blob->name.c_str(), out);

    __android_log_print(ANDROID_LOG_DEBUG, "yolov2TinyJni", "extract stop %d", result);
    __android_log_print(ANDROID_LOG_DEBUG, "yolov2TinyJni", "out.w = %d, out.h = %d", out.w, out.h);
   //if (result != 0)
        //return NULL;
    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;
    __android_log_print(ANDROID_LOG_DEBUG, "yolov2TinyJni", "output_wsize = %d", output_wsize);
    env->SetFloatArrayRegion(jOutputData, 0,  output_wsize * output_hsize,
                             reinterpret_cast<const jfloat *>(*output));  // copy
    env->SetFloatArrayRegion(jOutputData, 0,  output_wsize * output_hsize,
                             reinterpret_cast<const jfloat *>(*output));
    return jOutputData;

}
}

 

10、现在工程目录下新建CMakeLists.txt,编写cmakefile文件,主要是下面几个地方注意下:

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 2.8.10)#3.4.1

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
set(CMAKE_BUILD_TYPE RELEASE)

#include_directories(${ANDROID_SYSROOT}/usr/include/arm-linux-androideabi)

set(libs "${CMAKE_SOURCE_DIR}/src/main/jniLibs")
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/darknet2ncnn/include
        ${CMAKE_SOURCE_DIR}/src/main/cpp/ncnn/include
        ${CMAKE_SOURCE_DIR}/src/main/cpp/darknet/include
        ${CMAKE_SOURCE_DIR}/src/main/cpp/darknet2ncnn/src
        ${CMAKE_SOURCE_DIR}/src/main/cpp/ncnn/src)

set(CMAKE_STATIC_LINKER_FLAGS "-lm  -pthread -fopenmp -lstdc++")
set(CMAKE_C_FLAGS  "${CMAKE_C_FLAGS} -Ofast -Wno-unused-result  -Wfatal-errors -fPIC -fno-rtti -fno-exceptions")
set(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -std=c++11 -Ofast -Wno-unused-result  -Wfatal-errors -fPIC -fno-rtti -fno-exceptions -mfpu=neon-vfpv4")


add_library (libncnn STATIC IMPORTED)
set_target_properties(libncnn PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi-v7a/libncnn.a)

file(GLOB_RECURSE darknet_src ${CMAKE_SOURCE_DIR}/src/main/cpp/darknet/src/*.c)
#file(GLOB_RECURSE  DARKNET2NCNN_SRC ${CMAKE_SOURCE_DIR}/src/main/cpp/darknet2ncnn/src/*.cpp)
#file(GLOB_RECURSE DARKNET2NCNN_SRC_LAYER ${CMAKE_SOURCE_DIR}/src/main/cpp/darknet2ncnn/src/layer/*.cpp)

set(darknet2ncnn_dir ${CMAKE_SOURCE_DIR}/src/main/cpp/darknet2ncnn/src)
set(darknet2ncnn_src ${darknet2ncnn_dir}/layer/darknet_activation.cpp
    ${darknet2ncnn_dir}/layer/darknet_shortcut.cpp
    ${darknet2ncnn_dir}/layer/yolov1_detection.cpp
    ${darknet2ncnn_dir}/layer/yolov3_detection.cpp
    ${darknet2ncnn_dir}/object_detection.cpp
    ${darknet2ncnn_dir}/register_darknet.cpp
    ${darknet2ncnn_dir}/darknet2ncnn.cpp)

set(ncnn_src ${CMAKE_SOURCE_DIR}/src/main/cpp/ncnn/src)

set(lib_src ${darknet_src} ${darknet2ncnn_src} ${CMAKE_SOURCE_DIR}/src/main/cpp/yolov3-tiny-jni.cpp)

add_library( # Sets the name of the library.
        yolov3_tiny_jni

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        ${lib_src})

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

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
        android)
#find_library( # Sets the name of the path variable.
        #JniGraphics

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        #jnigraphics)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        yolov3_tiny_jni
        libncnn
        jnigraphics
        android
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

 

 

 

 

 

 

11、修改app的gradle文件

下面就是写几个java文件比较简单,就不详细说了,然后编译,在build\intermediates\cmake\debug\obj\armeabi-v7a文件下有编译生成的libyolov3_tiny_jni.so库文件,然后导入终端运行。

 

 

 

 

 

 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值