目录
一、背景
要开发一款在Android平台下的人脸识别软件,需要用到Android Caffe框架跑模型,需要生成不同平台(armeabi、armeabi-v7a、arm64-v8a、x86、x86_64)下的.so文件。大神项目源码 https://github.com/sh1r0/caffe-android-lib
二、准备工作
2.1 环境准备
按照要求,我们在ubuntu 16.04环境下安装Android NDK r11c ,参考这篇博客。安装cmake 3.5.2,参考这篇博客。
2.2 下载项目
本地创建目录(我是在/home目录下),执行(没有Git的自己先安装一下)
git clone --recursive https://github.com/sh1r0/caffe-android-lib.git
等待半个小时。。。
2.3 修改C++文件函数方法名
这一步可以说非常重要,因为你想生成的.so包是要放在自己的项目中的,而作为与JAVA native方法名对应的C++中的方法名,其格式是固定的,需要我们根据实际情况修改~
首先进入存放C++文件的目录
cd caffe-android-lib/caffe/android/
这时候你可以看到四个文件
| CMakeLists.txt | |
| caffe_jni.cpp | 需要修改的文件 |
| caffe_mobile.cpp | 定义了Caffe类和相关方法 |
| caffe_mobile.hpp | 定义了Caffe类和相关方法 |
我们只需要用vim编辑caffe_jni.cpp文件,我们可以看到好几个诸如下图所示的方法,这是个JNI方法,其命名也是有规律的
JNIEXPORT void JNICALL
Java_com_sh1r0_caffe_1android_1lib_CaffeMobile_setNumThreads
com_sh1r0_caffe_1android_1lib对应的包名为 com.sh1r0.caffe.android_lib
CaffeMobile对应调用该native方法的类名,最后的setNumThreads与JAVA里的native方法名一致
总结起来,这句话对应的是这么个类
package com.sh1r0.caffe.android_lib;
/**
* Created by shiro on 3/26/15.
*/
public class CaffeMobile {
public native void setNumThreads(int numThreads);
//todo
}
所以,请你确认自己的JAVA类名以及包名,比如我要编译的自己的类为
package ch.zhaw.facerecognitionlibrary.Helpers;
public class CaffeMobile {
public native void setNumThreads(int numThreads);
}
那么我就会将C++文件中的字符串
Java_com_sh1r0_caffe_1android_1lib_CaffeMobile
替换为
Java_ch_zhaw_facerecognitionlibrary_Helpers_CaffeMobile
为了方便替换,可以在vim中执行以下命令统一替换
%s/Java_com_sh1r0_caffe_1android_1lib_CaffeMobile/Java_ch_zhaw_facerecognitionlibrary_Helpers_CaffeMobile/g
保存退出即可
2.4 设置环境变量
以x86为例
export ANDROID_ABI=x86 #可选项 armeabi、armeabi-v7a、arm64-v8a、x86、x86_64
export NDK_ROOT=/path/to/ndk #如果你参考我的博客进行安装,目录就是/opt/ndk/android-ndk-r11c
三、编译项目
3.1 执行编译脚本
cd caffe-android-lib
./build.sh
如果。。。你没有遇到任何问题,看到了 Done!! 那么恭喜你,中奖了~~请忽略以下步骤直接跳到步骤四
如果很遗憾,编译退出,报错如下图所示
那么恭喜你,遇到了我~
接下来,请认真跟我操作
3.2 拷贝缺失文件
其实上图报错的文件是有的,已经生成了,为什么没有找到呢?感觉是作者写的脚本可能忘了把生成的文件移动到指定路径,先不管了,我们自己动手,丰衣足食~
(1)首先确认你所在的路径在caffe-android-lib/下
[email protected]:/home/caffe-android-lib#
(2)进入OpenBLAS目录
cd OpenBLAS/
这时候你执行查看命令 ll
你会发现有个文件名字很像我们要找的—— libopenblas_atomp-r0.2.18.a,多了个p,但是没关系,直接用它就可以~
(3)拷贝到对应目录
现在,执行命令
cp libopenblas.a /home/caffe-android-lib/android_lib/openblas/lib/
cp libopenblas_atomp-r0.2.18.a /home/caffe-android-lib/android_lib/openblas/lib/
细心的你发现了,我把两个文件都拷贝到了caffe-android-lib/android_lib/openblas/lib/目录下
我们还需要拷贝几个文件
执行以下命令,把lapack-netlib/LAPACKE/include目录下的文件都拷贝到指定路径下
cp -r lapack-netlib/LAPACKE/include/. /home/caffe-android-lib/android_lib/openblas/include/
可以看一下拷贝了哪些文件
拷贝后的文件关系,绿框中为新拷贝的文件
3.3 修改编译脚本
因为Openblas已经编译过了,所以我们要将build.sh脚本中相关内容注释掉
执行cd .. 回退进入到caffe-android-lib/目录
vim修改脚本,注释如图所示的几行,保存退出
3.4 再次编译脚本
执行 ./build.sh,等待编译完成
这次编译大概要花10多分钟。。。慢慢等
四、编译完成
编译好的.so文件在caffe-android-lib/android_lib/caffe/lib/下,如下图所示
至此大功告成~怎么取出来?自己想办法吧,反正我是用的XX云主机上的Ubuntu,用xshell的xftp工具直接下载下来了~