1、构建ncnn以及编译darknet2ncnn 参考:https://github.com/xiangweizeng/darknet2ncnn
git clone https://gitee.com/damone/darknet2ncnn.git
cd darknet2ncnn
git submodule init
git submodule update
cd darknet
make -j8
rm libdarknet.so
cd ncnn
mkdir build
cmake ..
make -j8
make install
.....
#https://github.com/xiangweizeng/darknet2ncnn
2、编译Androoid端ncnn库文件
#workspace ncnn
mkdir -p build-android-armv7
cd build-android-armv7
cmake -DCMAKE_TOOLCHAIN_FILE=/home/lw/Android/Sdk/ndk- bundle/build/cmake/android.toolchain.cmake \
-DANDROID_ABI="armeabi-v7a" \
-DANDROID_ARM_NEON=ON ..
make -j8
make install
在build-android-armv7文件夹下会生成install文件夹就是移植到Android端需要的库文件。
3、在Androoid端调用ncnn库文件,以及加载ncnn模型即可
新建Android工程,安装下面的步骤来
(1)右击file---New---New Project
(2)选择Native C++,next,语言选择java,next,选择C++11
(3)在工程目录main文件夹下新建assset和jniLibs两个文件夹,将之前编译的ncnn在Android下运行的库拷贝到jniLibs文件下
(4)将转换的yolov3-tiny的网络文件和权重文件拷贝到assets文件夹下,新建words.name文件,将类名写入改文件。
(5)在工程目录cpp文件夹下新建darknet、darknet2ncnn和ncnn三个文件夹,并分别将pc端darknet2ncnn下的incule和src、darknet2ncnn\darkent下的incule和src、darknet2ncnn\ncnn下的incule和src拷入对应的文件夹下。
(6)在工程目录cpp文件夹下新建yolov3-tiny-jni.cpp,部分代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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(*output)); // copy
env->SetFloatArrayRegion(jOutputData, 0, output_wsize * output_hsize,
reinterpret_cast(*output));
return jOutputData;
}
}
(7)现在工程目录下新建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})
编译后,在build\intermediates\cmake\debug\obj\armeabi-v7a文件下有编译生成的libyolov3_tiny_jni.so库文件,然后导入终端运行,Android端实现的yolov3-tiny,时间为500ms以内
参考:https://github.com/xiangweizeng/darknet2ncnn
参考:https://blog.csdn.net/liuwei36120516/article/details/103783870