请选择 进入手机版 | 继续访问电脑版

巨推链

币圈币圈
关注: 0贴子:3060 排名: 5 
0 回复贴,174 次查看
<返回列表

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

发表于 2020-2-27 11:58:40
yolov3-tiny:Android端基于darknet2ncnn之实现二-1.jpg        经过一段时间的反复摸索,终于在Android端基于darknet2ncnn的框架实现了yolov3-tiny,一张图片的检测时间为500ms以内,基本满足需求,接着分享该实现的第二部分内容,同时也欢迎大家关注我的微信公众号“机器视觉交流社”或个人微信号“LuckyZiXiao”进行交流。
[b]       前提:在pc端已经编译好darknet2ncnn环境,并且将Android下需要的nccn库文件也编译好,不清楚的可以参考我之前的文章。[/b]
新建Android工程,安装下面的步骤来
1、  右击file---New---NewProject
yolov3-tiny:Android端基于darknet2ncnn之实现二-2.jpg 2、选择Native C++
yolov3-tiny:Android端基于darknet2ncnn之实现二-3.jpg 3、next,语言选择java
yolov3-tiny:Android端基于darknet2ncnn之实现二-4.jpg 4、next,选择C11++
yolov3-tiny:Android端基于darknet2ncnn之实现二-5.jpg 5、在工程目录main文件夹下新建assset和jniLibs两个文件夹
yolov3-tiny:Android端基于darknet2ncnn之实现二-6.jpg 6、将之前编译的ncnn在Android下运行的库拷贝到jniLibs文件下
yolov3-tiny:Android端基于darknet2ncnn之实现二-7.jpg yolov3-tiny:Android端基于darknet2ncnn之实现二-8.jpg 7、将转换的yolov3-tiny的网络文件和权重文件拷贝到assets文件夹下,新建words.name文件,将类名写入该文件。
yolov3-tiny:Android端基于darknet2ncnn之实现二-9.jpg 8、在工程目录cpp文件夹下新建darknet、darknet2ncnn和ncnn三个文件夹,并分别将pc端darknet2ncnn下的incule和src、darknet2ncnn\darkent下的incule和src、darknet2ncnn\ncnn下的incule和src拷入对应的文件夹下。
yolov3-tiny:Android端基于darknet2ncnn之实现二-10.jpg 9、在工程目录cpp文件夹下新建yolov3-tiny-jni.cpp,部分代码如下:
#include &lt;android/bitmap.h&gt;
#include &lt;android/log.h&gt;
#include &lt;android/asset_manager_jni.h&gt;
#include &lt;jni.h&gt;
#include &lt;string&gt;
#include &lt;vector&gt;

#include &lt;sys/time.h&gt;
#include &lt;unistd.h&gt;

#include &lt;stdio.h&gt;
#include &lt;algorithm&gt;
#include &lt;fstream&gt;

#include &amp;#34;darknet2ncnn.h&amp;#34;
#include &amp;#34;ncnn/src/layer/input.h&amp;#34;
#include &amp;#34;ncnn_tools.h&amp;#34;

extern &amp;#34;C&amp;#34; {

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, &amp;#34;yolov3TinyJni&amp;#34;, &amp;#34;enter the jni func&amp;#34;);

     register_darknet_layer(yolo);

    const char *param_path = env-&gt;GetStringUTFChars( param, NULL);
    if(param_path == NULL)
        return JNI_FALSE;
    __android_log_print(ANDROID_LOG_DEBUG, &amp;#34;yolov3TinyJni&amp;#34;, &amp;#34;load_param %s&amp;#34;, param_path);

    //yolo.
    int ret = yolo.load_param(param_path);
    __android_log_print(ANDROID_LOG_DEBUG, &amp;#34;yolov3TinyJni&amp;#34;, &amp;#34;load_param result %d&amp;#34;, ret);
    env-&gt;ReleaseStringUTFChars( param, param_path);

    const char *bin_path = env-&gt;GetStringUTFChars( bin, NULL);
    if(bin_path == NULL)
        return JNI_FALSE;
    __android_log_print(ANDROID_LOG_DEBUG, &amp;#34;yolov3TinyJni&amp;#34;, &amp;#34;load_model %s&amp;#34;, bin_path);

    int ret2 = yolo.load_model(bin_path);
    __android_log_print(ANDROID_LOG_DEBUG, &amp;#34;yolov3TinyJni&amp;#34;, &amp;#34;load_model result %d&amp;#34;, ret2);
    env-&gt;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(&amp;#34;data&amp;#34;);

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

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

    __android_log_print(ANDROID_LOG_DEBUG, &amp;#34;yolov3TinyJniIn&amp;#34;, &amp;#34;yolov3_predict_has_input1, in.w: %d; in.h: %d&amp;#34;, 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(&amp;#34;data&amp;#34;,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-&gt;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&lt; out.h; i++) {
        for (int j = 0; j &lt; out.w; j++) {
            output[i*output_wsize + j] = &amp;out.row(i)[j];
        }
    }
    jfloatArray jOutputData = env-&gt;NewFloatArray(output_wsize * output_hsize);
    if (jOutputData == nullptr) return nullptr;
    __android_log_print(ANDROID_LOG_DEBUG, &amp;#34;yolov2TinyJni&amp;#34;, &amp;#34;output_wsize = %d&amp;#34;, output_wsize);
    env-&gt;SetFloatArrayRegion(jOutputData, 0,  output_wsize * output_hsize,
                             reinterpret_cast&lt;const jfloat *&gt;(*output));  // copy
    env-&gt;SetFloatArrayRegion(jOutputData, 0,  output_wsize * output_hsize,
                             reinterpret_cast&lt;const jfloat *&gt;(*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 &amp;#34;${CMAKE_SOURCE_DIR}/src/main/jniLibs&amp;#34;)
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 &amp;#34;-lm  -pthread -fopenmp -lstdc++&amp;#34;)
set(CMAKE_C_FLAGS  &amp;#34;${CMAKE_C_FLAGS} -Ofast -Wno-unused-result  -Wfatal-errors -fPIC -fno-rtti -fno-exceptions&amp;#34;)
set(CMAKE_CXX_FLAGS  &amp;#34;${CMAKE_CXX_FLAGS} -std=c++11 -Ofast -Wno-unused-result  -Wfatal-errors -fPIC -fno-rtti -fno-exceptions -mfpu=neon-vfpv4&amp;#34;)


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: &amp;#39;com.android.application&amp;#39;

android {
    compileSdkVersion 28
    buildToolsVersion &amp;#34;28.0.1&amp;#34;
    defaultConfig {
        applicationId &amp;#34;com.bket.yolov3Tiny&amp;#34;
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName &amp;#34;1.0&amp;#34;
        testInstrumentationRunner &amp;#34;androidx.test.runner.AndroidJUnitRunner&amp;#34;
        externalNativeBuild {
            cmake {
                cppFlags &amp;#34;-std=c++11 -Ofast -Wno-unused-result  -Wfatal-errors -fPIC -fno-rtti -fno-exceptions -fopenmp&amp;#34;
                abiFilters &amp;#34;armeabi-v7a&amp;#34;
                arguments &amp;#39;-DANDROID_PLATFORM=android-19&amp;#39;,
                        &amp;#39;-DANDROID_ARM_NEON=ON&amp;#39;

            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile(&amp;#39;proguard-android.txt&amp;#39;), &amp;#39;proguard-rules.pro&amp;#39;
        }
    }
    splits {
        abi {
            enable true
            reset()
            include &amp;#39;armeabi-v7a&amp;#39;
            universalApk false
        }
    }

    externalNativeBuild {
        cmake {
            path &amp;#34;CMakeLists.txt&amp;#34;
        }
    }
    sourceSets {
        main {
            jniLibs.srcDirs = [&amp;#34;src/main/jniLibs&amp;#34;]
            jni.srcDirs = [&amp;#39;src/cpp&amp;#39;]
        }
    }
}

dependencies {
    implementation fileTree(dir: &amp;#39;libs&amp;#39;, include: [&amp;#39;*.jar&amp;#39;])
    implementation &amp;#39;com.android.support:appcompat-v7:28.0.0&amp;#39;
    implementation &amp;#39;com.android.support.constraint:constraint-layout:1.1.3&amp;#39;
    testImplementation &amp;#39;junit:junit:4.12&amp;#39;
    implementation &amp;#39;com.github.bumptech.glide:glide:4.3.1&amp;#39;
    androidTestImplementation &amp;#39;com.android.support.test:runner:1.0.2&amp;#39;
    androidTestImplementation &amp;#39;com.android.support.test.espresso:espresso-core:3.0.2&amp;#39;
}
      下面就是写几个java文件比较简单,就不详细说了,然后编译,在build\intermediates\cmake\debug\obj\armeabi-v7a文件下有编译生成的libyolov3_tiny_jni.so库文件,然后导入终端运行。
yolov3-tiny:Android端基于darknet2ncnn之实现二-12.jpg yolov3-tiny:Android端基于darknet2ncnn之实现二-13.jpg
回复

使用道具 举报

  • 发布信息免费
  • 发贴彩色标题
  • 签到额外经验值

如何快速提升等级,查看[积分规则]

活动中心

查看更多>>
最新热版
会员排行
©2001-2018 巨推链 https://www.jutuilian.com/中国互联网举报中心 京ICP备14033863号-26 非经营性网站Powered byDiscuz!X3.3公安网备 
我们手机版广告合作客服QQ:1831288186Comsenz Inc.