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

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

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

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

1、 右击file---New---NewProject

2、选择Native C++

3、next,语言选择java

4、next,选择C11++

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

#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);

__android_log_print(ANDROID_LOG_DEBUG, "yolov3TinyJniIn", "yolov3_predict_has_input1, in.w: %d; in.h: %d", in.w, in.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);

//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;

}

}

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文件

apply plugin: 'com.android.application'

android {

compileSdkVersion 28

buildToolsVersion "28.0.1"

defaultConfig {

applicationId "com.bket.yolov3Tiny"

minSdkVersion 19

targetSdkVersion 28

versionCode 1

versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

externalNativeBuild {

cmake {

cppFlags "-std=c++11 -Ofast -Wno-unused-result -Wfatal-errors -fPIC -fno-rtti -fno-exceptions -fopenmp"

abiFilters "armeabi-v7a"

arguments '-DANDROID_PLATFORM=android-19',

'-DANDROID_ARM_NEON=ON'

}

}

}

buildTypes {

release {

minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

}

}

splits {

abi {

enable true

reset()

include 'armeabi-v7a'

universalApk false

}

}

externalNativeBuild {

cmake {

path "CMakeLists.txt"

}

}

sourceSets {

main {

jniLibs.srcDirs = ["src/main/jniLibs"]

jni.srcDirs = ['src/cpp']

}

}

}

dependencies {

implementation fileTree(dir: 'libs', include: ['*.jar'])

implementation 'com.android.support:appcompat-v7:28.0.0'

implementation 'com.android.support.constraint:constraint-layout:1.1.3'

testImplementation 'junit:junit:4.12'

implementation 'com.github.bumptech.glide:glide:4.3.1'

androidTestImplementation 'com.android.support.test:runner:1.0.2'

androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值