最近因为需要,尝试着将Dlib移植到android上。android小白一枚,做之前没接触过android,所以就用了别人说比较好的android studio 最新稳定版(windows下)。在android studio2.3.3版本中使用cmake+clang来编译C/C++。我直接将之前在Ubuntu17.04的跑通了的代码拿过来,之前用的cmake+gcc,所以CMakeList.txt也是直接复制过来稍加修改。因为用dlib一般少不了要用opencv的库,网上很多教程,我配置的时候一些问题基本都能从网上找到解决办法,就不在这里多说了。
其实弄好opencv之后,再把这个库加到项目里基本就没啥问题了,修改CmakeList.txt如下(这里是最基本的样子):
set(pathToProject D:/AndroidStudioProjects/MyProject)
set(pathToOpenCv D:/AndroidStudioProjects/OpenCV-android-sdk)
set(pathToDlib D:/AndroidStudioProjects/MyProject/app/src/main/dlib)
cmake_minimum_required(VERSION 3.4.1)
include(${pathToDlib}/dlib/cmake)
add_library( lib_opencv SHARED IMPORTED )
include_directories(lib_opencv ${pathToOpenCv}/sdk/native/jni/include )
set_target_properties( lib_opencv PROPERTIES IMPORTED_LOCATION ${pathToProject}/app/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)
add_library( native-lib SHARED src/main/cpp/native-lib.cpp )
find_library( log-lib log )
target_link_libraries( native-lib ${log-lib} lib_opencv dlib::dlib )
内容和dlib给的examples没啥太大差别。android studio 会自动把dlib加进项目中,然后编译就行啦。
(1)
error :no member named ‘round’ in namespace ‘std’; did you mean simply ‘round’?
一开始看到这个报错在网上翻了好多帖子,都没找到解决办法,无奈只能自己从头文件开始找起。把clang报错的内容拿出来看了,头文件包含路径没有问题,编译的参数没有问题(这个函数是从c++11之后才有的,所以有人会说在build.gradle里的cppFlags加上“-std=c++11”,这个在建项目的时候选C++11就已经加进去了啊,没啥用啊),最后就去看头文件cmath,在cmath中找到了这个函数的声明:
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// types
using ::double_t;
using ::float_t;
// functions
……
using ::round;
……
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
咋一看也没问题啊,可是上面这一段是包含在下面这两句里面的,-std=c++11
已经加了,所以就是那个宏的问题了。然后就去找,在别的头文件中确实有这个宏定义,但是那个头文件的引用顺序应该在cmath之后,所以才会出这个问题。
#if __cplusplus >= 201103L
#ifdef _GLIBCXX_USE_C99_MATH_TR1
知道问题之后解决起来就是各种办法了,一开始我直接在cmath中加了一句
#define _GLIBCXX_USE_C99_MATH_TR1 1
编译,没错。不过后来用这个关键词去检索,查到了stackoverflow上的一个类似的问题,按照里面的方法改了一下,也没问题。不过,
$ndk\sources\cxx-stl\gnu-libstdc++\libs\armeabi\include\bits\c++config.h
这个路径再自己看一下,好多个c++config.h,应该改哪个就根据实际来咯。
(2)
error: no type named ‘exception_ptr’ in namespace ‘std’; did you mean ‘exception’?
这个问题和上面的如出一辙,先去找对应的头文件
,在该文件的最后
#if (__cplusplus >= 201103L) && (ATOMIC_INT_LOCK_FREE > 1)
#include
#include
#endif
而std::exception_ptr
就是在
里面定义的,那就往回找ATOMIC_INT_LOCK_FREE
这个宏,在atomic_lockfree_defines.h
里面有如下宏定义:
#if __cplusplus >= 201103L
……
#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
……
#endif
参考预定义宏,用clang++.exe -E -dM - < nul
可以看到这个宏在clang里也是有的并且值为2(那为啥还会报错???黑人问号脸.jpg)。这里暂时先不管了,我直接把#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
改成了#define ATOMIC_INT_LOCK_FREE 2
,编译妥妥的,至于这两个宏,自己去查资料吧……
(3)
error: “DLIB_NO_GUI_SUPPORT is defined so you can’t use the GUI code. Turn DLIB_NO_GUI_SUPPORT off if you want to use it.”
这是移植过来又一个问题,因为之前在Ubuntu下面已经捯饬过dlib,所以大概知道问题出现在dlib的cmake文件中,DLIB_NO_GUI_SUPPORT
这个宏相关的在dlib/dlib/CMakeLists.txt
里面,可以自己看一下,下图是问题所在
在windows下面编译我怎么去给你弄这些包啊?那干脆注释掉好了。
(8月3日修改)在写程序测试的时候也遇到过一些问题,参考了github上的这个,Java的bitmap转换成mat,还有如何在Java里使用C++类等。
打算把dlib的人脸特征点提取使用在android程序上,但是dlib和opencv库的存储开销对一个小程序来说就有点大,如果大家有啥减少存储开销的好办法请留言我。