实验目的:

将caffe模型转成ncnn可以实现在移动端运行深度学习模型,主要使用:
https://github.com/Tencent/ncnn

实验环境:

1、系统环境

  • Mac OS Mojave系统
  • 编译好的caffe源码(可以参考我之前的博客:https://blog.csdn.net/sinat_28731575/article/details/78958348)

2、软件

  • Android Studio 3.2
  • Genymotion虚拟机
    (参考:http://www.open-open.com/lib/view/open1466430392743.html)

实验过程

1、实验准备

1、将 https://github.com/Tencent/ncnn clone到本地后解压,可以看到下面的组织结构:

其中

  • examples是简单的在安卓上使用NCNN的例子,有一个根据这个例子编译好的Android Studio工程: https://github.com/dangbo/ncnn-mobile
  • tools是后面需要用到的一些工具代码,包含了将各种网络转换到NCNN的代码

2、编译好的caffe源码用于后面转换模型使用

2、编译NCNN

(1)参照:https://github.com/Tencent/ncnn/wiki/how-to-build
中选择一个需要的环境编译,因为我需要在Android上面使用,所以选择了“Build for Android”:
这里首先需要安装NDK来编译Android项目,配置NDK环境有以下两种方式:

  • 使用Android Studio来直接安装:

    在偏好设置中进行如上图所示的配置,就可以配置NDK编译环境以及相关工具,安装好后NDK存放在上面的sdk目录下的ndk-bundle文件夹中

  • 自己到网站上面下载的方式:
    下载网址为:http://developer.android.com/ndk/downloads/index.html
    选择合适的版本下载(因为上面的第一种方法虽然简单,但是默认下载最新的NDK,在编译的时候可能会出现后面我会讲到的一些问题,所以这种方式可以根据实际需要选择合适的版本)
    解压上面下载的NDK压缩包
    使用下面的命令配置环境变量:

vim ~/.bash_profile# 在.bash_profile文件的最后添加上(路径根据自己的进行修改):
export PATH=$PATH:/Users/camlin_z/Data/Project/AndroidStudioProjects/android-ndk-r10e
# 或者想把环境变量添加成Android Studio配置的NDK的话:
export ANDROID_SDK="/Users/camlin_z/Library/Android/sdk"
export ANDROID_NDK="/Users/camlin_z/Library/Android/sdk/ndk-bundle"
export PATH="$PATH:$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools:$ANDROID_NDK"source ~/.bash_profile

或者想要替换Android Studio中的NDK环境为自己下的版本的话将上面下载的NDK压缩包重命名为ndk-bundle后放到sdk目录下即可

(2)编译libncnn.a
根据上面ncnn的github下的教程有:

$ cd <ncnn-root-dir>
$ mkdir -p build-android-armv7
$ cd build-android-armv7
$ cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \-DANDROID_ABI="armeabi-v7a" -DANDROID_ARM_NEON=ON \-DANDROID_PLATFORM=android-14 ..
$ make -j4
$ make install

即可“build armv7 library”,之后便会在build-android-armv7/install/lib目录下生成libncnn.a,这样ncnn的编译工作就完成了

3、使用NCNN将caffemodel转换成NCNN中需要的格式

参照上面ncnn的github下第二个教程:
https://github.com/Tencent/ncnn/wiki/how-to-use-ncnn-with-alexnet
首先是下载模型以及权重文件:

train.prototxt
deploy.prototxt
snapshot_10000.caffemodel

然后使用之前编译好的caffe中build/tools文件夹下的upgrade_net_proto_text和upgrade_net_proto_binary两个文件分别处理模型以及权重文件:

upgrade_net_proto_text [old prototxt] [new prototxt]
upgrade_net_proto_binary [old caffemodel] [new caffemodel]

同时要更改数据层的batchsize大小为1:

layer {name: "data"type: "Input"top: "data"input_param { shape: { dim: 1 dim: 3 dim: 227 dim: 227 } }
}

经过上面的步骤就准备好了需要转换的模型和权重文件。

接下来进入之前clone的 ncnn工程文件:

cd tools/caffe
mkdir build
cmake ..
make -j4

就可以在build文件夹中生成caffe2ncnn.cpp对应的可执行文件caffe2ncnn,最后执行:

caffe2ncnn deploy.prototxt bvlc_alexnet.caffemodel alexnet.param alexnet.bin

就可以得到最后转化的权重以及模型文件:alexnet.param alexnet.bin

4、编译jni生成了.so库文件

进入刚刚ncnn工程下的examples中,这是一个用squeeze net作为例子来生成动态链接库的例子,可以看到examples下面有已经按照3中步骤生成好的squeeze net对应的权重和模型文件,

进入的squeezencnn/jni文件夹中,可以看到如下文件架结构:

其中的cpp和h就是我们需要编写的C++文件和头文件,其中包含以下几个部分:

  • 我们需要的C++功能函数以及对应的头文件
  • C++和java之间的jni接口函数,用于两者之间的信息互通

然后在终端使用

ndk-build

命令就可以将上面的文件打包成一个 .so动态链接库供Android调用,可以参考:
https://blog.csdn.net/CrazyMo_/article/details/52804896 中的讲解,下面我以squeeze net这个例子简单说明一下安卓调用的过程:
首先是Android Studio工程中的结构为:

实际上上图中的工程顺序也就是我们建立我们工程的顺序:

  • 按照上面3中的步骤转换的模型就放在assets目录下
  • 然后我们除了MainActivity.java,就可以定义一个自己需要的函数接口类代码,比如这里的SqueezeNcnn.java,里面的内容为:
package com.tencent.squeezencnn;import android.graphics.Bitmap;
import android.content.Context;public class SqueezeNcnn
{// 我们自己定义的类方法,用于实现我们自己的功能(这里可以看到是java)public native boolean Init(byte[] param, byte[] bin, byte[] words);public native String Detect(Bitmap bitmap);static {System.loadLibrary("squeezencnn");}
}

然后可以参考:https://blog.csdn.net/createchance/article/details/53783490
来自动生成jni文件夹下的squeezenet_v1.1.id.h和squeezencnn_jni.cpp,然后在其中进一步编写我们需要实现的功能函数

  • 接着就是JNI代码了,这个部分实际上包含了实现功能的C/C++代码以及jni接口函数两部分,通过上面的生成,我们得到了squeezenet_v1.1.id.h和squeezencnn_jni.cpp,对应于上面SqueezeNcnn.java中的类方法,squeezencnn_jni.cpp中有对应的JNI接口函数:

    (函数具体内容大家可以到ncnn工程中查看,这里为了说明方便隐去内容)
    可以看到jni接口函数是在java类函数的前面加上了
Java_com_tencent_squeezencnn_SqueezeNcnn_

部分,将java的native方法转换成C函数声明的规则是这样的:Java_{package_and_classname}_{function_name}(JNI arguments)。包名中的点换成单下划线。需要说明的是生成函数中的两个参数:
JNIEnv *:这是一个指向JNI运行环境的指针,后面我们会看到,我们通过这个指针访问JNI函数
jobject:这里指代java中的this对象

而对于一些不是接口的功能函数,我们就可以使用C++或者C来编写,而不需要考虑jni

  • 最后就是将上面的代码编译成libsqueezencnn.so动态库
    这里我们首先需要编写jni目录下的编译配置文件 Android.mk 和 Application.mk ,类似于C++编译中的CMakeLists.txt:

Android. mk :

LOCAL_PATH := $(call my-dir)# change this folder path to yours
NCNN_INSTALL_PATH := /Users/camlin_z/Data/Project/AndroidStudioProjects/ncnn-master/build-android-armv7/installinclude $(CLEAR_VARS)
LOCAL_MODULE := ncnn
# LOCAL_SRC_FILES := $(NCNN_INSTALL_PATH)/$(TARGET_ARCH_ABI)/libncnn.a
LOCAL_SRC_FILES := $(NCNN_INSTALL_PATH)/lib/libncnn.a
include $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := squeezencnn
LOCAL_SRC_FILES := squeezencnn_jni.cppLOCAL_C_INCLUDES := $(NCNN_INSTALL_PATH)/includeLOCAL_STATIC_LIBRARIES := ncnnLOCAL_CFLAGS := -O2 -fvisibility=hidden -fomit-frame-pointer -fstrict-aliasing -ffunction-sections -fdata-sections -ffast-math
LOCAL_CPPFLAGS := -O2 -fvisibility=hidden -fvisibility-inlines-hidden -fomit-frame-pointer -fstrict-aliasing -ffunction-sections -fdata-sections -ffast-math
LOCAL_LDFLAGS += -Wl,--gc-sectionsLOCAL_CFLAGS += -fopenmp
LOCAL_CPPFLAGS += -fopenmp
LOCAL_LDFLAGS += -fopenmpLOCAL_LDLIBS := -lz -llog -ljnigraphicsinclude $(BUILD_SHARED_LIBRARY)

具体里面的配置方法可以参考:
http://www.cnblogs.com/wainiwann/p/3837936.html

Application. mk:

# APP_STL := stlport_static
APP_STL := gnustl_static
# APP_ABI := armeabi armeabi-v7a# 注意此处哟啊对应你之前编译ncnn时的版本,比如我之前用的就是armeabi-v7a
# 下面就要指定为armeabi-v7a,不能再有后面的arm64-v8a
APP_ABI := armeabi-v7a #arm64-v8aAPP_PLATFORM := android-14
# NDK_TOOLCHAIN_VERSION := 4.9

写好上面的各个配置文件之后就可以在终端进入jni文件夹输入:

ndk-build

命令进行编译生成 libsqueezencnn. so动态链接库,经过了以上的所有步骤得到最后的动态链接库,Android中的函数就可以直接调用来实现对应的功能了

Caffe转NCNN并移植Android配置记录相关推荐

  1. 深度学习-服务端训练+android客户端物体识别实战(caffe+mobilenet+ncnn+android)

    文章目录 背景 物体识别简介 自动驾驶 淘宝京东使用物体识别技术 公司业务需求 深度学习简介 深度学习的位置 深度学习概念 深度学习优势 深度学习基础知识 感知机 激活函数 多层感知机 卷积神经网络 ...

  2. MTK6735 android开发记录 编译配置(一)

    MTK6735 android开发记录 编译配置(一) 指导文件:环境建立,编译,配置GPIO等: :YYW_M_6735相关文档\YYW-M-6735-Support.pdf 里面有什么不懂的,比如 ...

  3. 【非原创】Ubuntu14.04+cuda6.5+opencv2.4.9+caffe配置记录

    Ubuntu14.04+cuda6.5+opencv2.4.9+caffe配置记录 从4月5日差不多开始安装,到今天4月15日,快两个星期了.如果加上之前自己看点Linux的时间,这折腾的有两个星期( ...

  4. 移植mysql到安卓手机_记录dbnet文本检测转ncnn并移植到安卓上

    目前,文本检测主要分为基于检测网络和分割网络实现,上文(风影:记录densenet-ocr识别网络转ncnn并移植到安卓手机)讲到将yolo3文本检测+densenet识别网络转ncnn推理,并成功移 ...

  5. 全志A33移植ubuntu系统记录(1)V1.0(分色排版)

    http://blog.csdn.net/lushengchu_luis/article/details/72457449 全志A33移植ubuntu系统记录(1) 大文实验室/大文哥 壹捌陆捌零陆捌 ...

  6. 3g android4 移植 飞思卡尔i.MX 6Quad Android 4.2.2的中兴和Ublox 3G驱动移植 Android——4.2 - 3G移植之路

    点击打开链接 3g android4 移植 点击打开链接 飞思卡尔i.MX 6Quad Android 4.2.2的中兴和Ublox 3G驱动移植 点击打开链接  Android--4.2 - 3G移 ...

  7. win8下cocos2dx3.2移植android平台及代码打包APK

      cocos2dx程序不能只在VS2012下运行,迟早是要搬运到Android和IOS上的.Windows下移植IOS平台先搁下不说比较困难,而且只有越狱的苹果机才可以运行,而且毕竟IOS高端.小众 ...

  8. Android 学习记录(持续更新)

    Android 学习记录(持续更新) 1.AndroidManifest.xml 详解: http://www.jb51.net/article/73731.htm (AndroidManifest. ...

  9. Ubuntu20.04安装与配置记录

    Ubuntu20.04安装与配置记录 原文地址:Ubuntu20.04安装与配置记录 一.Ubuntu系统盘制作 1.1 Windows环境下制作系统盘 下载Ubuntu系统,选择桌面版. 下载工具系 ...

最新文章

  1. app-》h5同步身份
  2. 一次分表踩坑实践的探讨
  3. 基于linux的ARM设备升级,烧写Nand flash总结
  4. python记录_day14 内置函数二 迭代 二分法
  5. IoU 判断矩形区域重叠
  6. 红米note2移动4g在哪里显示无服务器,红米note2移动版能用联通4g吗?红米note2插联通卡用法介绍...
  7. MySQL分片 --转自Peter Zaitsev对MySQL分片的建议
  8. 安卓学习第10课——listview
  9. 斗地主AI算法——第十六章の样例分析
  10. linux nand 坏块_韦东山-NAND 上面都是坏块怎么办啊? - 百问网嵌入式问答社区
  11. 理解 JavaScript 的 async/await
  12. python open w_python-文件操作示例
  13. 函数可以作为Javascript对象(哈希表)的键吗
  14. 一个完整的物联网项目管理流程
  15. 电力拖动自动控制系统(序)
  16. [后端开发]支付宝支付接口调试 (Python v3.6)
  17. RxSwift 介绍与简单使用
  18. 宝宝吃饭不乖,怎么办?
  19. 机器学习数学基础-最大似然估计与贝叶斯法则
  20. Unity相机设置CullingMask

热门文章

  1. CAD画图-部分图形简述
  2. Linux系统特殊符号总结
  3. 链游开发公司 区块链游戏开发公司
  4. 鸿蒙内核源码分析表,鸿蒙内核源码分析(双向链表篇) | 谁是内核最重要结构体 ? | 开篇致敬鸿蒙内核开发者 | v1.10...
  5. python学习笔记Day4 面向对象编程,文件操作,os模块,代码调试
  6. 酒店商场地铁站刷脸应用场景无处不在
  7. matlab shift 详解,Matlab fftshift 详解
  8. 苹果IOS内购验单完整流程,in_app购买收据处理
  9. [学习笔记]Spring Cloud详细教程(二)
  10. 样本熵、排列熵及散布熵优缺点对比